The scenario is this:
There are 13 items in a projection in total. In default Orchard displays 2 pages (10 on the 1st, 3 on the 2nd page). If the user is on the 2nd page then chooses the option to show 50, then Orchard leaves the ?page=2 in the url and it messes the pager up. Showing 51-13 of 13 items. A bug report has been filled with the community behind Orchard, but I though someone could help with this, as it's a small code snippet. I guess the Javascript at the end needs to be modified, but I'm not really sure...
The pager.cshtml (copied from AdminView):
#{
Model.PreviousText = T("<");
Model.NextText = T(">");
var routeData = new RouteValueDictionary(ViewContext.RouteData.Values);
var queryString = ViewContext.HttpContext.Request.QueryString;
if (queryString != null) {
foreach (string key in queryString.Keys) {
if (key != null && !routeData.ContainsKey(key)) {
var value = queryString[key];
routeData[key] = queryString[key];
}
}
}
if (routeData.ContainsKey("id") && !HasText(routeData["id"])) {
routeData.Remove("id");
}
var totalPageCount = (int)Math.Ceiling((double)Model.TotalItemCount / Model.PageSize);
Model.Metadata.Type = "Pager_Links";
IHtmlString pagerLinks = Display(Model);
Model.Classes.Add("selector");
var pageSizeTag = Tag(Model, "ul");
if (Model.RouteData != null) {
foreach (var rd in Model.RouteData.Values) {
routeData[rd.Key] = rd.Value;
}
}
var pageSizes = new List<int?> { 10, 50, 100 };
var defaultPageSize = WorkContext.CurrentSite.PageSize;
if (!pageSizes.Contains(defaultPageSize)) {
pageSizes.Add(defaultPageSize);
}
Script.Require("jQuery");
}
#if (Model.TotalItemCount > 1) {
<div class="pager-footer">
<span class="page-results">#T("Showing {0} - {1} of {2} jobs", (Model.Page - 1) * (int)Model.PageSize + 1, Model.PageSize == 0 ? Model.TotalItemCount : Math.Min(Model.TotalItemCount, (Model.Page) * (int)Model.PageSize), Model.TotalItemCount)</span>
#if (totalPageCount > 1 || Model.PageSize == 0 || Model.PageSize > pageSizes.First()) {
<div class="page-size-options group">
#T("Show:") #pageSizeTag.StartElement
#{ routeData["pageSize"] = 0; }
#if ((int)Model.PageSize == 0) {
<li class="selected"><span>#T("All").ToString()</span></li>
} else {
<li>#Display.ActionLink(Value: T("All"), Action: (string)routeData["action"], Controller: (string)routeData["controller"], RouteValues: routeData)</li>
}
#foreach (int size in pageSizes.OrderBy(p => p)) {
routeData["pageSize"] = size;
if ((int)Model.PageSize == size) {
<li class="selected"><span>#size.ToString()</span></li>
} else {
<li>#Display.ActionLink(Value: size, Action: (string)routeData["action"], Controller: (string)routeData["controller"], RouteValues: routeData)</li>
}
}
#pageSizeTag.EndElement
</div>
}
#if (totalPageCount > 1 || Model.PageSize != 0) {
#pagerLinks
}
</div>
}
#using (Script.Foot()) {
<script type="text/javascript">
//<![CDATA[
$(function () {
$('ul.selector').each(function () {
var self = $(this),
options = $.map(self.find("li"), function (li) {
var self = $(li);
return $("<option/>", {
value: self.children("a").attr("href"),
text: self.text(),
selected: self.hasClass("selected")
})[0];
}),
select = $("<select/>", {
id: self.attr("id") + "Selector",
"class": self.attr("class"),
name: self.attr("name") + "Selector"
}).change(onSelectChange).append(options);
self.replaceWith(select);
});
function onSelectChange() {
// redirect to page with new page size
// disable button so that no other value can be chosen while the form is submited
window.location = $(this).attr("disabled", true).val();
}
})
//]]>
</script>
}
I've found the fix on codeplex
I'll give it a try.
Related
I have made a list. I've added some dropdown to sort the list. Once its sorted, I would like to be able to reset the dropdown back to nothing. (Accomplished that already). But the list doesn't update back to as if nothing was selected. How can I do that?
Code im using to manipulate the list:
<script>
$.noConflict();
jQuery( document ).ready(function( $ ) {
$('.container').on("change", 'select', function() {
var type = $('#BBFHtype').val().toLowerCase(),
surface = $('#BBFHsurface').val().toLowerCase(),
sticking = $('#BBFHsticking').val().toLowerCase(),
panel = $('#BBFHpanel').val().toLowerCase(),
height = $('#BBFHheight').val().toLowerCase(),
thickness = $('#BBFHthickness').val().toLowerCase();
var table = $("#BBFHDoors");
var trs = table.find('tr');
trs.hide();
var filtered = trs.filter(function(index, elem) {
var tds = $(elem).find('td');
if (type !== "all" && tds.eq(1).text().trim().toLowerCase() !== type) {return false;}
if (surface !== "all" && tds.eq(2).text().trim().toLowerCase() !== surface) {return false;}
if (sticking !== "all" && tds.eq(3).text().trim().toLowerCase() !== sticking) {return false;}
if (panel !== "all" && tds.eq(4).text().trim().toLowerCase() !== panel) {return false;}
if (height !== "all" && tds.eq(5).text().trim().toLowerCase() !== height) {return false;}
if (thickness !== "all" && tds.eq(6).text().trim().toLowerCase() !== thickness) {return false;}
return true;
})
filtered.show();
if (filtered.length == 0) {
alert("No Records Found!!!");
}
});
});
</script>
Code im using to reset the selections back to nothing:
$(function () {$("#btnReset").bind("click", function ()
{$("#BBFHtype")[0].selectedIndex = 0;
$("#BBFHsurface")[0].selectedIndex = 0;
$("#BBFHsticking")[0].selectedIndex = 0;
$("#BBFHpanel")[0].selectedIndex = 0;
$("#BBFHheight")[0].selectedIndex = 0;
$("#BBFHthickness")[0].selectedIndex = 0;
});});
Ive tried playing around with .prop and .attr(selected), and removeattr(). But haven't been successful. EX: $("#BBFHtype")[0].prop("selected", true);
Any help would be awesome!
Just trigger change on the select elements:
$('select').trigger('change');
Complete function:
$(function () {$("#btnReset").bind("click", function ()
{$("#BBFHtype")[0].selectedIndex = 0;
$("#BBFHsurface")[0].selectedIndex = 0;
$("#BBFHsticking")[0].selectedIndex = 0;
$("#BBFHpanel")[0].selectedIndex = 0;
$("#BBFHheight")[0].selectedIndex = 0;
$("#BBFHthickness")[0].selectedIndex = 0;
$('select').trigger('change');
});});
Also, see complete working demo here
I hope someone can help me but I have just started learning javascript and I have been working on a quiz for a page of a learning website that I am helping to create. I have been asked to add a message that pops up at the end of the quiz but I can't seem to get it to work. Please excuse any terrible obvious mistakes as like I said I have only been looking into it for a couple of days.
I have a div in the html called message that I wanted to the message to appear.
This is the js I have so far. Any tips would be massively appreciated.
(function($) {
$.fn.emc = function(options) {
var defaults = {
key: [],
scoring: "normal",
progress: true
},
settings = $.extend(defaults,options),
$quizItems = $('[data-quiz-item]'),
$choices = $('[data-choices]'),
itemCount = $quizItems.length,
chosen = [],
$option = null,
$label = null;
emcInit();
if (settings.progress) {
var $bar = $('#emc-progress'),
$inner = $('<div id="emc-progress_inner"></div>'),
$perc = $('<span id="emc-progress_ind">0/'+itemCount+'</span>');
$bar.append($inner).prepend($perc);
}
function emcInit() {
$quizItems.each( function(index,value) {
var $this = $(this),
$choiceEl = $this.find('.choices'),
choices = $choiceEl.data('choices');
for (var i = 0; i < choices.length; i++) {
$option = $('<input name="'+index+'" id="'+index+'_'+i+'" type="radio">');
$label = $('<label for="'+index+'_'+i+'">'+choices[i]+'</label>');
$choiceEl.append($option).append($label);
$option.on( 'change', function() {
return getChosen();
});
}
});
}
function getChosen() {
chosen = [];
$choices.each( function() {
var $inputs = $(this).find('input[type="radio"]');
$inputs.each( function(index,value) {
if($(this).is(':checked')) {
chosen.push(index + 1);
}
});
});
getProgress();
}
function getProgress() {
var prog = (chosen.length / itemCount) * 100 + "%",
$submit = $('#emc-submit');
if (settings.progress) {
$perc.text(chosen.length+'/'+itemCount);
$inner.css({height: prog});
}
if (chosen.length === itemCount) {
$submit.addClass('ready-show');
$submit.click( function(){
return scoreNormal();
});
}
}
function scoreNormal() {
var wrong = [],
score = null,
$scoreEl = $('#emc-score');
for (var i = 0; i < itemCount; i++) {
if (chosen[i] != settings.key[i]) {
wrong.push(i);
}
}
$quizItems.each( function(index) {
var $this = $(this);
if ($.inArray(index, wrong) !== -1 ) {
$this.removeClass('item-correct').addClass('item-incorrect');
} else {
$this.removeClass('item-incorrect').addClass('item-correct');
}
});
score = ((itemCount - wrong.length) / itemCount).toFixed(2) * 100 + "%";
$scoreEl.text("You scored a "+score).addClass('new-score');
}
function print(message) {
document.write(message);
}
if (score===100){
print('congratulations');
}else if(score<=99){
print('Try Again');
}
}
}(jQuery));
$(document).emc({
key: ["1","2","1","1","1","1"]
});
Popup Message
form controls tags
template literal interpolation
nested ternaries
Event Delegation
CSS transform and transition driven by .class
Demo
Enter a number in the <input>. To close the popup message, click the X in the upper righthand corner.
$('#quiz').on('change', function(e) {
var score = parseInt($('#score').val(), 10);
var msg = `Your score is ${score}<sup>×</sup><br>`;
var remark = (score === 100) ? `Perfect, great job!`: (score < 100 && score >= 90) ? `Well done`: (score < 90 && score >= 80) ? `Not bad`: (score < 80 && score >= 70) ? `You can do better`:(score < 70 && score >= 60) ? `That's bad`: `Did you even try?`;
$('#msg legend').html(`${msg}${remark}`).addClass('newScore');
$('#msg legend').on('click', 'sup', function(e) {
$(this).parent().removeClass('newScore');
});
});
#msg legend {
position: absolute;
z-index: 1;
transform: scale(0);
transition: 0.6s;
}
#msg legend.newScore {
font-size:5vw;
text-align:center;
transform-origin: left bottom;
transform: scale(2) translate(0,70%);
transition: 0.8s;
}
#msg legend.newScore sup {
cursor:pointer
}
<form id='quiz'>
<fieldset id='msg'>
<legend></legend>
<input id='score' type='number' min='0' max='100'> Enter your test score in the range of 0 to 100
</fieldset>
</form>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
This is a simple quiz/questionnaire, that'll display results of the quiz on submission. It shows the results, but only for about half a second before resetting the page. I would also like for the page to show an alert if the user says they're under 18 when the quiz is submitted; it wouldn't keep them from seeing the answers, but just giving them a message.
function checkAge() {
if(age<18) {
alert("Always make sure you have adult supervision while caring for and handling any venomous arachnid.");
} }
function generateAnswers() {
var choice1score = 0;
var choice2score = 0;
var choice3score = 0;
var choice4score = 0;
}
var chosenAnswers = document.getElementsByTagName('result');
for (i=0; i<chosenAnswers.length; i++) {
if (chosenAnswers[i].checked) {
// add 1 to that choice's score
if (chosenAnswers[i].value == 'choice1') {
choice1score = choice1score + 1;
}
if (chosenAnswers[i].value == 'choice2') {
choice2score = choice2score + 1;
}
if (chosenAnswers[i].value == 'choice3') {
choice3score = choice3score + 1;
}
if (chosenAnswers[i].value == 'choice4') {
choice4score = choice4score + 1;
}
}
}
var maxscore = Math.max(choice1score,choice2score,choice3score,choice4score);
var resultBox = document.getElementById('result');
if (choice1score == maxscore) {
resultBox.innerHTML = "Asian Forest Scorpion"
}
if (choice2score == maxscore) {
resultBox.innerHTML = "Deathstalker Scorpion"
}
if (choice3score == maxscore) {
resultBox.innerHTML = "Desert Hairy Scorpion"
}
if (choice4score == maxscore) {
resultBox.innerHTML = "Emperor Scorpion"
}
}
This is where I put the code:
https://codepen.io/cryceks/pen/vjgzOZ
Use:
event.preventDefault();
This prevents the webpage from reloading and therefore clearing form data
i would like to ask for help in a simple task i really need to do at my work (I am a javascript newbie). I made a simple collapsible list with script provided by this guy http://code.stephenmorley.org/javascript/collapsible-lists/ but what i need right now are two simple buttons as stated in the title: expand all and collapse whole list. Do you guys know if something like that can be implemented in this certain script? Please help :)
var CollapsibleLists = new function () {
this.apply = function (_1) {
var _2 = document.getElementsByTagName("ul");
for (var _3 = 0; _3 < _2.length; _3++) {
if (_2[_3].className.match(/(^| )collapsibleList( |$)/)) {
this.applyTo(_2[_3], true);
if (!_1) {
var _4 = _2[_3].getElementsByTagName("ul");
for (var _5 = 0; _5 < _4.length; _5++) {
_4[_5].className += " collapsibleList";
}
}
}
}
};
this.applyTo = function (_6, _7) {
var _8 = _6.getElementsByTagName("li");
for (var _9 = 0; _9 < _8.length; _9++) {
if (!_7 || _6 == _8[_9].parentNode) {
if (_8[_9].addEventListener) {
_8[_9].addEventListener("mousedown", function (e) {
e.preventDefault();
}, false);
} else {
_8[_9].attachEvent("onselectstart", function () {
event.returnValue = false;
});
}
if (_8[_9].addEventListener) {
_8[_9].addEventListener("click", _a(_8[_9]), false);
} else {
_8[_9].attachEvent("onclick", _a(_8[_9]));
}
_b(_8[_9]);
}
}
};
function _a(_c) {
return function (e) {
if (!e) {
e = window.event;
}
var _d = (e.target ? e.target : e.srcElement);
while (_d.nodeName != "LI") {
_d = _d.parentNode;
}
if (_d == _c) {
_b(_c);
}
};
};
function _b(_e) {
var _f = _e.className.match(/(^| )collapsibleListClosed( |$)/);
var uls = _e.getElementsByTagName("ul");
for (var _10 = 0; _10 < uls.length; _10++) {
var li = uls[_10];
while (li.nodeName != "LI") {
li = li.parentNode;
}
if (li == _e) {
uls[_10].style.display = (_f ? "block" : "none");
}
}
_e.className = _e.className.replace(/(^| )collapsibleList(Open|Closed)( |$)/, "");
if (uls.length > 0) {
_e.className += " collapsibleList" + (_f ? "Open" : "Closed");
}
};
}();
It is important to understand why a post-order traversal is used. If you were to just iterate through from the first collapsible list li, it's 'children' may (will) change when expanded/collapsed, causing them to be undefined when you go to click() them.
In your .html
<head>
...
<script>
function listExpansion() {
var element = document.getElementById('listHeader');
if (element.innerText == 'Expand All') {
element.innerHTML = 'Collapse All';
CollapsibleLists.collapse(false);
} else {
element.innerHTML = 'Expand All';
CollapsibleLists.collapse(true);
}
}
</script>
...
</head>
<body>
<div class="header" id="listHeader" onClick="listExpansion()">Expand All</div>
<div class="content">
<ul class="collapsibleList" id="hubList"></ul>
</div>
</body>
In your collapsibleLists.js
var CollapsibleLists =
new function(){
...
// Post-order traversal of the collapsible list(s)
// if collapse is true, then all list items implode, else they explode.
this.collapse = function(collapse){
// find all elements with class collapsibleList(Open|Closed) and click them
var elements = document.getElementsByClassName('collapsibleList' + (collapse ? 'Open' : 'Closed'));
for (var i = elements.length; i--;) {
elements[i].click();
}
};
...
}();
I have created a javascript filter that is working but not all the time. To first see this in action, visit the following link. On the left side, click on the Bridgestone e6 link under "Brand Model". It returns nothing, but in reality it should return 3 products in the view.
The way the filter works is as follows. I grab the value of the item clicked on the sidebar, then I search the html elements in the main view to see if there are any matches. If there are, I only show those products in the view and hide the rest.
The javascript that takes care of this is (also you can see it here):
Is it some whitespace issue or something incorrect in my JS? I tried to use the jQuery trim function to no avail.
The javascript:
var noProductMatches = jQuery('.no-products-found');
jQuery('#filter-by-brand li a').click(function()
{
noProductMatches.hide();
var brandNameSelected = jQuery(this).html();
var productVendorFromCollection = jQuery("#product-vendor");
var productContainer = jQuery('#product-collection .productBoxWrapper');
if (brandNameSelected == 'All Brands' )
{
productContainer.fadeIn("slow");
}
else
{
var results = jQuery(".productBoxWrapper")
.fadeOut(100)
.delay(100)
.filter(function()
{
return jQuery(this).html().indexOf(brandNameSelected) > -1 || jQuery(this).html().indexOf(productVendorFromCollection) > -1;
})
.each(function(index, item)
{
jQuery(item).fadeIn("slow");
});
if (results.length == 0)
{
noProductMatches.fadeIn();
}
}
});
jQuery('#filter-by-model li a').click(function()
{
noProductMatches.hide();
var brandNameSelected = jQuery.trim(jQuery(this).html());
var productContainer = jQuery('#product-collection .productBoxWrapper');
if (brandNameSelected == 'Any Model' )
{
productContainer.fadeIn("slow");
}
else
{
var results = productContainer
.fadeOut(100)
.delay(100)
.filter(function()
{
return jQuery.trim(jQuery(this).html()).indexOf(brandNameSelected) > -1;
})
.each(function(index, item)
{
jQuery(item).fadeIn("slow");
});
if (results.length == 0)
{
noProductMatches.fadeIn();
}
}
});
jQuery('#filter-by-price li a').click(function()
{
noProductMatches.hide();
var priceRangeSelectedItem = jQuery(this).html();
var minSelectedPrice = parseInt( jQuery(this).attr("name") );
var maxSelectedPrice = parseInt( jQuery(this).attr("title") );
var productContainer = jQuery('#product-collection .productBoxWrapper');
if (priceRangeSelectedItem == 'Any Price')
{
productContainer.fadeIn("slow");
}
else
{
var results = jQuery(".productBoxWrapper")
.fadeOut(100)
.delay(100)
.filter(function()
{
var minProductPrice = parseInt( jQuery(this).find("#lowestPriceRange").html() );
var maxProductPrice = parseInt( jQuery(this).find("#highestPriceRange").html() );
//alert(minProductPrice);
//alert(maxProductPrice);
return (minProductPrice >= minSelectedPrice && maxProductPrice <= maxSelectedPrice);
})
.each(function(index, item)
{
jQuery(item).fadeIn("slow");
});
if (results.length == 0)
{
noProductMatches.fadeIn();
}
}
});
The problem is that it is mixed case. In the menu it says Bridgestone e6 but on the page it says Bridgestone E6, with an uppercase E. Either you have to make everything lowercase when you search our make sure they are equal in the menu and on the page.