Apply different DIV in For each loop - model-view-controller

I am working on MVC 5. Using WEB API, fetch the data now it is time to apply the HTML PAGE design and CSS.
#foreach (var item in Model)
{
if (Model.First() == item)
{
///APPLY FIRST RECORD CSS:- Works FINE
}
else {
<div class="row">
<div class="col-sm-4">
</div>
</div>
}
}
In the else portion, every time it generates the new ROW for a SINGLE record. But I am interested to display record 2 3 4 in SECOND ROW. 5 6 7 Record in the THIRD ROW and so on.

If it is the first item, open a div and then put the items in it. Close the div when the number of columns is 3 or close the div if the item is at the end of the list.
The following algorithm does this for you
#{
int i = 0;
int columnCounter = 1;
bool newRow = false;
}
#foreach (var item in Model)
{
//add and open div row
if (i == 0 || newRow)
{
newRow = false;
#:<div class="row" style="border:2px solid red;">
}
<div class="col-md-4" style="padding:0;">
<div style="height:40px;background:#f6f6f6;width:100%;text-align:center;">
<span>Column #i</span>
</div>
</div>
//close div row if column count == 3 or reach of end list
if (columnCounter == 3 || i == Model.Count - 1)
{
newRow = true;
columnCounter = 1;
#:</div>
}
else
{
columnCounter = columnCounter + 1;
}
}
result:

Related

Ajax / How to make appended list item "selected"?

I am cycling through all values of items array and appending them to #selectbox like this:
$("#Selectbox").append(
$("<option></option>").attr(
"value", items[i][0]).text(items[i][1])
);
How within the same loop cycle I could make particular item "selected"? Thanks
You can check if the item is what you want to select like this:
const items = [1, 2, 3];
const selected = 2;
for(var i in items) {
let item = items[i];
let option = $("<option></option>");
if(item == selected) {
option.attr('selected', true);
}
$("#Selectbox").append(option.attr("value", item).text(item));
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select id="Selectbox">
<option>Select an item</option>
</select>

Check timing validation with scope in laravel

I store 2 dates in my products table start_discounted and end_discounted this 2 columns are responsible of my discount price duration. Now when my product discount duration expires except it return back to normal price it stays on discounted price and my timer goes to minus.
Codes
my model scope
public function scopeValidDiscount($query){
return $query->where('start_discounted', '<=', Carbon::now()->toDateTimeString())
->where('end_discounted', '>=', Carbon::now()->toDateTimeString());
}
controller
public function product($slug){
$product = Product::where('slug', $slug)->firstOrFail();
$validdiscount = $product->ValidDiscount()->get();
//...
}
blade
#if($validdiscount)
show timer
#endif
PS: I need to avoid showing timer in 2 conditions, 1 discount dates are expired. 2 Product discount dates are null.
Any idea where is my mistake?
UPDATE
My timer in blade:
#if($validdiscount)
<div class="deals_timer row align-items-center">
<div class="col-md-6 deals_timer_title_container">
<div class="deals_timer_title">{{__('store.hurryup')}}</div>
<div class="deals_timer_subtitle">{{__('store.endsin')}}</div>
</div>
<div class="col-md-6 deals_timer_content ml-auto">
<div class="deals_timer_box clearfix" data-target-time="{{$end}}">
<div class="text-center deals_timer_unit">
<div id="deals_timer3_hr" class="deals_timer_hr"></div>
<span>{{__('store.hours')}}</span>
</div>
<div class="text-center deals_timer_unit">
<div id="deals_timer3_min" class="deals_timer_min"></div>
<span>{{__('store.mins')}}</span>
</div>
<div class="text-center deals_timer_unit">
<div id="deals_timer3_sec" class="deals_timer_sec"></div>
<span>{{__('store.secs')}}</span>
</div>
</div>
</div>
</div>
#endif
Please pay attention to data-target-time="{{$end}}" i think the issue might be here...
my timer script:
<script>
$(document).ready(function(){
if($('.deals_timer_box').length)
{
var timers = $('.deals_timer_box');
timers.each(function()
{
var timer = $(this);
var targetTime;
var target_date;
// Add a date to data-target-time of the .deals_timer_box
// Format: "Feb 17, 2018"
if(timer.data('target-time') !== "")
{
targetTime = timer.data('target-time');
target_date = new Date(targetTime).getTime();
}
else
{
var date = new Date();
date.setDate(date.getDate() + 2);
target_date = date.getTime();
}
// variables for time units
var days, hours, minutes, seconds;
var h = timer.find('.deals_timer_hr');
var m = timer.find('.deals_timer_min');
var s = timer.find('.deals_timer_sec');
setInterval(function ()
{
// find the amount of "seconds" between now and target
var current_date = new Date().getTime();
var seconds_left = (target_date - current_date) / 1000;
console.log(seconds_left);
// do some time calculations
days = parseInt(seconds_left / 86400);
seconds_left = seconds_left % 86400;
hours = parseInt(seconds_left / 3600);
hours = hours + days * 24;
seconds_left = seconds_left % 3600;
minutes = parseInt(seconds_left / 60);
seconds = parseInt(seconds_left % 60);
if(hours.toString().length < 2)
{
hours = "0" + hours;
}
if(minutes.toString().length < 2)
{
minutes = "0" + minutes;
}
if(seconds.toString().length < 2)
{
seconds = "0" + seconds;
}
// display results
h.text(hours);
m.text(minutes);
s.text(seconds);
}, 1000);
});
}
});
</script>
{{$end}}
This is what I have in my controller in order to get my expired date and use if in my JavaScript above:
$mytime = Carbon::now();
if(!empty($product->start_discounted && $product->end_discounted)){
$start = $product->start_discounted->format('M d, Y');
$end = $product->end_discounted->format('M d, Y');
}
then I also have my scope code:
$validdiscount = $product->ValidDiscount()->get();
now what I think is that my issue cause by: I get my expire date from
product directly $product->end_discounted while I try to avoid it while I'm using scope which
it does the same carbon thing in my model, not sure! (maybe i should get my $end by scope as well?
You're not using scopes correctly. Scopes are used on query builder, not on an already retrieved model.
For doing this, you just need a regular method:
public function validDiscount() {
return $this->start_discounted <= now()->toDateTimeString()
&& $this->end_discounted >= now()->toDateTimeString();
}
And then in your view, check it like this:
#if($product->validDiscount())
show timer
#endif
And remove the unneeded $validdiscount = $product->ValidDiscount()->get(); (where you're using a query scope on an instance of a model).
You can use javascript/jquery in front end to do it.
When you populate that page, call that js function to check that value like this $(document).ready(function(){ check_timer() })
Then trigger that method again when you timer has expired to update your view(hide promotional price, hide timer & showing actual price)
check_timer function can be like this
function check_timer(){
if(!{{ $validdiscount }}){
//hide your required div
}
}

Validate an input field in order to be unique and non duplicate in jQuery mobile

In my jQuery mobile app I have an alarm service the user enter number of alarms Per day , once the user enters the number of alarms lets say 3 , app will create 3 input fields for time , when the user clicks save button to save data i need to validate all the created input time fields so the entered time not equal the current time, and be unique there is no alarms at this time , I have solved it by the following code but the problem is that when the user enter a unique time " a non repeated time" I change the exist value from true to false but it didn't enter and execute this condition
else if (exist == false && $(this).attr('value') != currentTime ) directly "once " the exist value is updated ,I need to click the save button again in order to make the code know that the exist value is changed , and continue saving the alarm data in the DB .
How can i solve this problem ? please help me ...
<body>
<div data-role="page" id="Alarm">
<div data-role="header" ></div>
<div data-role="content" >
<form>
<input type="number" id="AlarmTimes"/>
<label for="AlarmTimes" > Number of alarms Per day </lable>
<div id="timeFields" style="display:none;" >
</div>
<div>
<input type="button" id="SaveBtn" value="Save Alarm "/></div>
</form>
</div>
</div>
</body>
javascript
var alarm_TimesNum;
var exist = true;
var ExistAlarmTimesArr = [];
$('#AlarmTimes').on('keyup' , function(){
alarm_TimesNum = $('#AlarmTimes').attr('value');
var timeFields = $('#timeFields');
if(timeFields.children().length != 0 )
{
timeFields.empty();
timeFields.hide();
}
for( var i=1 ; i<= alarm_TimesNum ;i++)
{
timeFields.append($( '<div class="ui-grid-a" ><div class="ui-block-a"> <input type="time" name="alarmTime" class="AlarmTime" /></div>'
+'<div class="ui-block-b" ><label for=" alarmTime" ><font size="5px" style="font- weight: normal;" class="Time_label"> Time:: </font></label></div></div>'));
timeFields.trigger('create');
}
timeFields.show();
});
db.transaction(getExistAlarmsTime,transError,transSuccess);
$('#SaveBtn').on('click',function(){
$('.AlarmTime').each(function(i){
if( $(this).attr('value') == currentTime || $.trim( $(this).attr('value')).length ==0 )
{
$('.Time_label').each(function(j){ if(j==i){ $(this).addClass('missing');} });
if(i==0){ alert('Enter time for alarm 1 '); }
else if(i==1){alert('Enter time for alarm 2 '); }
else if(i==2){alert('Enter time for alarm 3 '); }
}
else if( $(this).attr('value') != currentTime && exist == true )
{
for( var k=0;k<ExistAlarmTimesArr.length;k++)
{
if( $(this).attr('value') == ExistAlarmTimesArr[k])
{
$('.Time_label').each(function(j){ if(j==i){ $(this).addClass('missing');} });
if(i==0){alert( 'Enter Another Time for alarm 1 you have another alarm at this time '); }
else if(i==1){ alert( 'Enter Another Time for alarm 2 you have another alarm at this time '); }
else if(i==2){ alert( 'Enter Another Time for alarm 3 you have another alarm at this time '); }
exist = true;
break;
}
else { exist = false; }
}
}
else if (exist == false && $(this).attr('value') != currentTime )
{
$('.Time_label').each(function(j){ if(j==i){ $(this).removeClass('missed');} });
NotifTime = $(this).attr('value');
TimeArr[j] = NotifTime;
j= j+1 ;
count ++;
}
});
// save data in the DB
});
function getExistAlarmsTime(tx)
{
tx.executeSql("SELECT Time FROM AlarmTBL ",[],AlarmTimeExist,transError);
}
function AlarmTimeExist(tx,result)
{
for(var j=0;j< result.rows.length; j++)
{
var row = result.rows.item(j);
ExistAlarmTimesArr[j] = row['Time'];
}
}
I think the issue could just be the use of .attr('value'), try subbing it for .val() instead. I think that will fix your issues.

Separate LI's by child element

i have the following code:
HtmlAgilityPack.HtmlNodeCollection nodeCollection = bodyNode.SelectNodes("//ul[#class='myClass']//li");
which grabs about 250 LI's
the UL format is a bit weird and it goes like this:
<ul>
<li>
<h5>Parent</h5>
Some more tags here...
</li>
<li>
<h4>Child of the prev li</h4>
</li>
<li>
<h4>Child of the prev li</h4>
</li>
<!-- and so on -->
<!-- Then again -->
<li>
<h5>Parent</h5>
Some more tags here...
</li>
<li>
<h4>Child of the prev li</h4>
</li>
<li>
<h4>Child of the prev li</h4>
</li>
<!-- child li's are not constant, this is only for demo -->
</ul>
i need to separate the LI's into groups where each group contains the parent LI and all the children LI's
anyone can help with this?
If I understood correctly this is want you want
HtmlNodeCollection liList = doc.DocumentNode.SelectNodes("//ul//li");
List<List<HtmlNode>> liGroups = new List<List<HtmlNode>>();
List<HtmlNode> liGroup = null;
foreach (HtmlNode li in liList)
{
if (li.InnerText.Contains("Parent"))
{
if (liGroup != null)
liGroups.Add(liGroup);
liGroup = new List<HtmlNode>();
liGroup.Add(li);
}
else
{
liGroup.Add(li);
}
}
liGroups.Add(liGroup);
What you will have at the end is a list liGroups that will have other list liGroup. For your above html it will show that liGroups have 2 liGroup because in your above html you have 2 parents and both two liGroup will have 3 li (1 parent + 2 childs) because both parents have same amount of children.
After that you do with them whatever you want for example:
MessageBox.Show(liGroups[0][2].InnerText); //Show from the first group the 3rd's li InnerText
var tree = new Dictionary<HtmlNode, List<HtmlNode>>();
foreach (var node in nodeCollection)
if (node.SelectSingleNode("h5[text()='Parent']") != null)
tree.Add(node, new List<HtmlNode>());
else
tree.Last().Value.Add(node);
or
var groups = nodeCollection.Group();
static class Extensions
{
public static ILookup<HtmlNode, HtmlNode> Group(this HtmlNodeCollection collection)
{
return collection.Where(n => !n.IsParent()).ToLookup(n => n.GetParent());
}
public static bool IsParent(this HtmlNode node, string header = "Parent")
{
var h = node.Element("h5");
return h != null && h.InnerText == header;
}
public static HtmlNode GetParent(this HtmlNode node)
{
while (!node.IsParent())
node = node.PreviousSibling;
return node;
}
}

prototype findElements querySelectorAll error

i'm call the "down" function but am getting an invalid argument using 1.6.1_rc2
here's the html snippet:
<TR id=000000214A class="activeRow searchResultsDisplayOver" conceptID="0000001KIU">
<TD>
<DIV class=gridRowWrapper>
<SPAN class=SynDesc>Asymmetric breasts</SPAN>
<DIV class=buttonWrapper>
<SPAN class=btnAddFav title="Add to Favorites"> </SPAN>
</DIV>
</DIV>
</TD>
</TR>
here's the code:
var description = row.down('span.SynDesc').innerHTML;
row is a dom reference to the element.
prototype is appending a # then the id of the element:
findElements: function(root) {
root = root || document;
var e = this.expression, results;
switch (this.mode) {
case 'selectorsAPI':
if (root !== document) {
var oldId = root.id, id = $(root).identify();
id = id.replace(/[\.:]/g, "\\$0");
e = "#" + id + " " + e;
}
results = $A(root.querySelectorAll(e)).map(Element.extend); <-- e = "#000000214A span.SynDesc"
root.id = oldId;
return results;
case 'xpath':
return document._getElementsByXPath(this.xpath, root);
default:
return this.matcher(root);
}
i get an "invalid argument" error?
if i put a breakpoint before the offending line and change e to be equal to "span.SynDesc" it works fine.
help. :)
I ran into this. Changing the TR's ID to start with a letter should fix the problem. It turns out that legal HTML IDs match /^[A-Za-z][A-Za-z0-9_:.-]*$/.

Resources