Loading page info into array, and cycling page info as URLs - javascript

I;ve built a CMS that allows users to build static pages of images and text content solely for displaying on television screens throughout our building. I've completed this to the point of viewing the display with it's pages but only if I call it explicitly in the url. The problem is, I want to load by display which is stored in the URL.
For instance, the url now if you click on Display 3 is http://local.CMSTest.com/showDisplay.php?display=3
and this calls a function using 3 as the display ID that grabs all pages with that display ID. This works, but in my html where I throw a foreach in there, it loads both pages associated with that display into a crammed page, half and half. So I know it's working but I need to store these pages into an array for javascript as well I believe.
I'm thinking there may be a way where I can load it with the first page on default and append it to the url like http://local.CMSTest.com/showDisplay.php?display=3&page_id = 2 and then after the time is up, it can go to the next one and change the URL http://local.CMSTest.com/showDisplay.php?display=3&page_id = 3
So the PHP and HTML is working at this moment:
<div class="row top">
<?php include 'banner.php'?>
</div>
<div class="row middle" style="background-image: url(<?php echo $showDisplays['background_img']?>);">
<div class="col-lg-12">
<?if($showDisplays['panel_type_id'] == 1){?>
<div class="fullContent" style=" height: 100%; ">
<?php echo $showDisplays['content']?>
</div>
<?}?>
</div>
</div>
<div class="row bottom">
<?php include 'ticker.php';?>
</div>
<?php }?>
I want to try some javascript like this that will take each page from the array, replacing the following URLs with page IDs from my previous array. How can I do this properly?
<script type="text/javascript">
var Dash = {
nextIndex: 0,
dashboards: [
{url: "http://www.google.com", time: 5},
{url: "http://www.yahoo.com", time: 10},
{url: "http://www.stackoverflow.com", time: 15}
],
display: function()
{
var dashboard = Dash.dashboards[Dash.nextIndex];
frames["displayArea"].location.href = dashboard.url;
Dash.nextIndex = (Dash.nextIndex + 1) % Dash.dashboards.length;
setTimeout(Dash.display, dashboard.time * 1000);
}
};
window.onload = Dash.display;
</script>
UPDATE:
Current array
Array ( [pageID] => 104 [page_type_id] => 1 [display_id] => 3 [slide_order] => [active] => 1 [background_img] => [panel_id] => 96 [panel_type_id] => 1 [page_id] => 104 [cont_id] => 148 [contID] => 148 [content] =>This is full content)

First you would need to access your php array from javascript and you can do that by using php's json_encode which will convert the array to a JSON object.
Then you can use URL search params to alter the query parameters for the next URL which you can call. See the below example
function setDisplay() {
let params = new URL(document.location).searchParams;
let pageID = params.get("pageID");
let disply = params.get("display");
// set the html based on pageID and display
}
function getNextURL() {
// encode your php array to json
// let obj = <?php echo json_encode($myArray); ?>;
// probably what obj will look like after above line
// this is just for this example, you should use the line commented out above
var obj = {
"pageID": 104,
"page_type_id": 1,
"display_id": 3,
}
let params = new URL(document.location).searchParams;
params.set("pageID", obj.pageID);
params.set("display", obj.display_id);
let url = window.location.href.split('?')[0];
let nextURL = url + "?" + params.toString();
console.log(nextURL);
return nextURL
}
getNextURL();

You would need to
parse the frames.displayArea.location.href for its query parameters.
assign to Dash.nextIndex either (params.page_id + 1) % Dash.dashboards.length because the page_id is the currently diplaying page and we want the next page... or 0 if params.page_id is undefined.
build your URL from dashboard.url appending the display_id and page_id parameters.
For cleanliness, I recommend creating a var called newURL since we need to build a custom string.
display: function() {
// step 1
let queryString = frames.displayArea.location.href.split("?")[1];
let paramArr = queryString.split("&");
let params = {};
paramArr.forEach((param) => {
let [name, value] = param.split("=");
params[name] = value;
})
console.log("params: ", params)
// step 2
Dash.nextIndex = (params.page_id)
? (params.page_id + 1) % Dash.dashboards.length
: 0;
var dashboard = Dash.dashboards[Dash.nextIndex];
// step 3
let newURL = dashboard.url + "?display_id=" + params.display_id
+ "&page_id=" + Dash.nextIndex;
// Unrelated nit: bracket access IMHO should only be used when specifying a
// property by the string value contained in a variable, or when the
// property name would be an invalid javascript variable name (starting
// with a number, including spaces, etc)
frames.displayArea.location.href = newURL;
setTimeout(Dash.display, dashboard.time * 1000);
}

Related

How to load more data in ng-repeat if there's not enough?

I have a filter in ng-repeat and ng-if condition and there almost always will be less then 10 results per page (10 results is what I get from API).
My idea is that in js file should be a cycle with condition
First we declare variable so we can check the length
var numberOfArticlesOnPage = container.children.length
console.log(numberOfArticlesOnPage)
for (i = 0; numberOfArticlesOnPage < 10); i++ {
$scope.pageNumber = $scope.pageNumber + 1
var i=1
i++
$http(
{
method: 'GET',
url:
//Here I put i instead of page number so it loads next page and every time we create results[i] with new number in the end
'https://api.nytimes.com/svc/search/v2/articlesearch.json?fq=news_desk:("Politics")&page=' + i + '&api-key=groQeNemKAhk7QjDWircgauo5jYVcwez', /* Most recent */
}).then(function successCallback(result) {
$scope.results[i] = result.data.response.docs;
}, function errorCallback(result) {
console.log("there's a error, man...");
});
//Check the length again
var container = document.querySelector(".container");
var numberOfArticlesOnPage = container.children.length```
//And that is the template where it should be shown
```<div class="container">
<div class="box" ng-repeat="result in results | filter : '!trump'" ng-if="result.multimedia[2].url != null">
<h2>{{result.headline.main}}</h2>
<p class="abstract">{{result.abstract}}</p>
<img src="https://static01.nyt.com/{{result.multimedia[0].url}}">
<p></p>
<a ui-sref="article ({
articleSlug:'{{result.headline.main | slugify}}',
title: '{{result.headline.main}}',
url: '{{result.web_url}}',
image: 'https://static01.nyt.com/{{result.multimedia[0].url}}',
externalUrl: '{{result.url}}'
})">Read more...</a>
</div>
</div>```
//But I don't know how to write a code in the template so it can take more data?

angular 7 add html with binding after view init

I have an issue here,
i want to add to my html this code
<dx-report-viewer [reportUrl]="reportUrl" height="800px">
<dxrv-request-options [invokeAction]="invokeAction" [host]="hostUrl">
</dxrv-request-options>
</dx-report-viewer>
but only after getting params from
self.queryParams = self.route.queryParams.subscribe(params => {
if (params['id']) {
self.ReportId = params['id']; // (+) converts string 'id' to a number
console.log(self.ReportId);
self.reportUrl += "ReportId=" + self.ReportId;
}
Because otherwise the url will be wrong ...
but i can't get it work is it because dx-report is a directive from an external library ?
If someone can help would be great !!
Create a property and default it to false:
paramsAdded: boolean = false;
Wrap the report element in a div using *ngIf:
<div *ngIf="paramsAdded">
<dx-report-viewer [reportUrl]="reportUrl" height="800px">
<dxrv-request-options [invokeAction]="invokeAction" [host]="hostUrl">
</dxrv-request-options>
</dx-report-viewer>
</div>
When the parameters are available set the property to true to render the report element(s):
self.queryParams = self.route.queryParams.subscribe(params => {
if (params['id']) {
self.ReportId = params['id']; // (+) converts string 'id' to a number
console.log(self.ReportId);
self.reportUrl += "ReportId=" + self.ReportId;
self.paramsAdded = true;
}

How to Paginate a Computed Property in Vue

I am creating a Vue app, where a list of jobs will be displayed and this data is coming from a JSON object. In this app I also am adding filtering functionality as well as pagination. So what I have so far is:
<div id="app" v-cloak>
<h2>Location</h2>
<select v-model="selectedLocation" v-on:change="setPages">
<option value="">Any</option>
<option v-for="location in locations" v-bind:value="location" >{{ location }}</option>
</select>
<div v-for="job in jobs">
<a v-bind:href="'/job-details-page/?entity=' + job.id"><h2>{{ job.title }}</h2></a>
<div v-if="job.customText12"><strong>Location:</strong> {{ job.customText12 }}</div>
</div>
<div class="paginationBtns">
<button type="button" v-if="page != 1" v-on:click="page--">Prev</button>
<button type="button" v-for="pageNumber in pages.slice(page-1, page+5)" v-on:click="page = pageNumber"> {{pageNumber}} </button>
<button type="button" v-if="page < pages.length" v-on:click="page++">Next</button>
</div>
<script>
var json = <?php echo getBhQuery('search','JobOrder','isOpen:true','id,title,categories,dateAdded,externalCategoryID,employmentType,customText12', null, 200, '-dateAdded');?>;
json = JSON.parse(json);
var jsonData = json.data;
var app = new Vue({
el: '#app',
data() {
return {
//assigning the jobs JSON data to this variable
jobs: jsonData,
locations: ['Chicago', 'Philly', 'Baltimore'],
//Used to filter based on selected filter options
selectedLocation: '',
page: 1,
perPage: 10,
pages: [],
}
},
methods: {
setPages () {
this.pages = [];
let numberOfPages = Math.ceil(this.jobs.length / this.perPage);
for (let i = 1; i <= numberOfPages; i++) {
this.pages.push(i);
}
},
paginate (jobs) {
let page = this.page;
let perPage = this.perPage;
let from = (page * perPage) - perPage;
let to = (page * perPage);
return jobs.slice(from, to);
},
}
watch: {
jobs () {
this.setPages();
}
},
})
computed: {
filteredJobs: function(){
var filteredList = this.jobs.filter(el=> {
return el.customText12.toUpperCase().match(this.selectedLocation.toUpperCase())
});
return this.paginate(filteredList);
}
}
</script>
So the issue I am running into is that I want the amount of pages to change when the user filters the list using the select input. The list itself changes, but the amount of pages does not, and there ends up being a ton of empty pages once you get past a certain point.
I believe the reason why this is happening is the amount of pages is being set based on the length of the jobs data object. Since that never changes the amount of pages stays the same as well. What I need to happen is once the setPages method is ran it needs to empty the pages data array, then look at the filteredJobs object and find the length of that instead of the base jobs object.
The filteredJobs filtering is a computed property and I am not sure how to grab the length of the object once it has been filtered.
EDIT: Okay so I added this into the setPages method:
let numberOfPages = Math.ceil(this.filteredJobs.length / this.perPage);
instead of
let numberOfPages = Math.ceil(this.jobs.length / this.perPage);
and I found out it is actually grabbing the length of filteredJobs, but since I am running the paginate method on that computed property, it is saying there is only 10 items in the filteredJobs array currently and will only add one pagination page. So grabbing the length of filteredJobs may not be the best route for this. Possibly setting a data variable to equal the filtered jobs object may be better and grab the length of that.

Can I assign multiple data-id values to one attribute in one element?

I use WordPress. I have an audio player on my site. When a user clicks the play button on an individual song, it will play the song. The post ID is how the player determines which song to play.
So in the DIV that wraps the button tag, I assign an attribute: data-id which is the post id of the song. My app then grabs the MP3 file that is associated with that post ID. Simple.
My play button tag is essentially this:
<div class="item item-action" data-id="1161">
<button class="btn-playpause"></button>
</div>
The important parts of my player.js file that handles the click event and plays the song is below:
Simulate the play button
// simulate the play btn
$(document).on('click.btn', '.btn-playpause, .btn-queque', function(e){
e.stopPropagation();
var self = $(this),
item = $(this).closest('.item'),
id = item.attr('data-id'),
type = item.data('user-id') ? 'user' : 'post',
play = true;
if(!player){
getItem(id, type).done(function(obj){
if(obj.status == 'success'){
mep.mepPlaylistTracks = obj.tracks;
initPlayer();
player && player.mepSelect(0, true);
}
});
return;
}
if(self.is('.btn-queque')){
play = false;
self.parent().dropdown('toggle');
}
if( self.hasClass('is-playing') ){
self.removeClass('is-playing');
player.pause();
}else{
var index = player.find(id);
if( index !== -1){
var track = player.mepGetCurrentTrack();
if(track && track.id == id && !play) return;
player.mepSelect(index, true);
}else{
getItem(id, type).done(function(obj){
if(obj.status == 'success'){
addToPlay(obj.tracks, play);
}
});
}
}
});
getItem() function
function getItem(id, type){
return $.ajax({
type : "post",
dataType : "json",
url : ajax.ajax_url,
data : {action: "ajax_music", id : id, type: type, nonce: ajax.nonce}
});
}
addToPlay() function
function addToPlay(obj, play){
if(obj.length == 1){
player.mepAdd( obj[0], play );
}else if(obj.length > 1){
if(play){
player.options.mepPlaylistTracks = obj;
player.updatemepList();
player.mepSelect(0, true);
}else{
for(var i=0; i<obj.length; i++){
player.mepAdd( obj[i] );
}
}
}
}
You can see that once I click the play button, depending on a condition, it fires the getItem() function. getItem() takes the data-id attribute defined earlier as the id variable and begins to play the song.
The addToPlay() function will add another song to the playlist if there is already an instance of the player open. And when a user clicks another play button, it will add that new song to the list and begin to play that song.
Is it possible to modify this code so that I can add multiple data-id values to my button code so that my script will recognize there is more than one song id and add those to my playlist, using the addToPlay() function?
I'd like to do something like this
<div class="item item-action" data-id="1161, 1288, 1456">
<button class="btn-playpause"></button>
</div>
The reason I want to do this, is I would like to add a feature that will allow my users to Play All Songs on the current page they're viewing. Some of our pages, like the catalog page, displays dozens of songs that fit a certain criteria and I'd like the option to play all songs on the page.
Can anyone help push me in the right direction?
Thanks.
You could store a JSON encoded array in the data-id tag. Like:
<div class="item item-action" data-id='[1161, 1288, 1456]'>
<button class="btn-playpause"></button>
</div>
Then you can parse the array, and loop over its contents, adding each id to the queue.
See an example of parsing here: https://gist.github.com/charliepark/4266921
Here I present a alternative method.
In your markup, you can set the data-id='[1234] attribute as an encoded array. You can then collect those properties and set them as the data id property on a given element using jQuery as I illustrate here:
let someElement = $('.item');
let setItems = someElement.data('id');
let thisItem = someElement.attr('data-id');
IMPORTANT: the someElement.data('id') returns the same as the someElement.attr('data-id') (except as a string) IF nothing for that element has been set with someElement.data('id',[567,890]); which sets the property id for someElement. So, once set that way
let x = someElement.data('id'); // returns the array 567,890
let org = someElement.attr('data-id'); // still returns the [1234]
This code illustrates:
let someElement = $('.item').first();
let setItems = someElement.data('id');
let thisItemS = someElement.attr('data-id');
// make an array of the string
let thisItem = JSON.parse(thisItemS);
console.log(typeof setItems, setItems, typeof thisItemS, thisItemS, typeof thisItem, thisItem);
someElement.data('id', [567, 890]);
let x = someElement.data('id'); // returns and gets the array 567,890
let org = JSON.parse(someElement.attr('data-id')); // still returns the string [1234] made into an array
// merge with no duplicates, in the other code I used .map()
let z = Array.from(new Set(x.concat(org)));
console.log(x, org, z);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<div class='item' data-id='[1234]'>me the item</div>
This code show a set of elements using the concepts introduced above plus:
Set some check boxes for selection
Get the values (all)
Get the values (checkbox checked)
You can combine any of this for your original purpose, but you will need to manage that addition of new items values (and subsequently how to remove perhaps) on a given element. You might even add to a <select> element so the user then can pick some to remove perhaps...
function showPicks(choicedata) {
let ul = $('#choices').append('<ul />');
//ul.remove('li');
ul.html('empty');
ul.text('choices:');
$.each(choicedata, function(index, choice) {
let c = $('<li/>').html(choice);
ul.append(c);
});
}
$(function() {
let mydata = $('.item').map(function() {
return $(this).data('id');
}).get();
$('.all-items').data("id", mydata);
showPicks(mydata); //now do what is desired
});
$('item.item-action').filter(':not(".some-items")')
.on('click', '.btn-playpause', function() {
let setItems = $(this).closest('.item').data('id');
let thisItem = $(this).closest('.item').attr('data-id');
// do what you wish here, I show them
showPicks(setItems);
});
$('.some-items').on('click', '.btn-playpause', function(event) {
let mydata = $('.item-select').filter(':checked')
.add(this) // set an additional one from the button
.closest('.item')
.map(function() {
return $(this).data('id');
}).get();
$(event.delegatedTarget).data("id", mydata);
let setItems = $(event.delegatedTarget).data('id');
// the original pick
let thisItem = $(event.delegatedTarget).attr('data-id');
// do what you wish here
showPicks(mydata);
});
.btn-playpause {
height: 2em;
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<div class="item item-action" data-id="[1161]">
<button class="btn-playpause" type="button"></button>
<input type="checkbox" class="item-select" />
</div>
<div class="item item-action" data-id="[1163]">
<button class="btn-playpause"></button>
<input type="checkbox" class="item-select" />
</div>
<div class="item item-action" data-id="[9961,7744]">
<button class="btn-playpause" type="button"></button>
<input type="checkbox" class="item-select" />
</div>
<div class="item item-action all-items" data-id="[42]">
<button class="btn-playpause" type="button">Play All</button>
</div>
<div class="item item-action some-items" data-id="[95]">
<button class="btn-playpause" type="button">Play selected</button>
</div>
<div id="choices">none</div>

Count how many times a data-attribute or text string exists in a string and return the number for each one

I have a little PHP & JavaScript app that cURL requests a list of URLs and writes to a log file when any URL in that list of URLs returns a, 404 or 500 status code for example.
Ok what I am trying to do is count with JavaScript how many of each URL exists in the log file and return the number. I want to return a structure kind of like this:
<ul>
<li>http://www.example.com (5)</li>
<li>http://anothersite.org (19)</li>
<li>http://www.more.com (16)</li>
</ul>
In the log file I have given each URL entry a data-attribute and looks like this:
<p class="log-text">
<span data-url="www.examplezz.com">www.examplezz.com - 0 (Timeout)</span>
<span data-url="www.examplezz.com/othersite">www.examplezz.com/othersite - 0 (Timeout)</span>
<span data-url="www.idontexist.io">www.idontexist.io - 0 (Timeout)</span>
<span data-url="www.idontexist.io/othersite">www.idontexist.io/othersite - 0 (Timeout)</span>
</p>
<p class="log-text">
<span data-url="www.examplezz.com">www.examplezz.com - 0 (Timeout)</span>
<span data-url="www.examplezz.com/othersite">www.examplezz.com/othersite - 0 (Timeout)</span>
<span data-url="www.idontexist.io">www.idontexist.io - 0 (Timeout)</span>
<span data-url="www.idontexist.io/othersite">www.idontexist.io/othersite - 0 (Timeout)</span>
</p>
<p class="log-text">
<span data-url="www.examplezz.com">www.examplezz.com - 0 (Timeout)</span>
</p>
The log file is fetched via ajax, and I get it as a string. Here is a JS Bin with the "for" loop I have been trying to work with: JSBin
Additional info: Here is what my ajax request looks like, not sure if it helps.
var overLoad = function (){
$.ajax({
type: 'POST',
url: 'includes/logfiles/'+logfilename+'.php',
data: $('.log-text'),
statusCode: {
404: function() {
$("<p class='intro log-text eventNum' style='margin-bottom:0;'>Is your internet connection intact?</p>").appendTo(".overview-popup");
}
}
}).done(function (data) {
// here I want to count the urls in the 'data' string
}).fail(function (jqXHR, statusCode) {
$("<p class='intro log-text eventNum' style='margin-bottom:0;'>No offline events!</p>").appendTo(".overview-popup");
});
};
Why try to do string manipulation when you have the DOM at your finger tips?
var div = document.createElement('div');
div.innerHTML = data;
var elements = div.querySelectorAll('[data-url]');
var urls = {};
for(var i = 0; i < elements.length; i++) {
var url = elements[i].getAttribute('data-url');
if(!(url in urls)) {
urls[url] = 0;
}
urls[url]++;
}
console.log(urls);
http://jsbin.com/adEBiCU/3/edit
I leave the grouping by host name (instead of just url) to you as an exercise. Hint: use the DOM (double hint: <a> has a host property).
Edit: I missed that you're already using jQuery.
var data ='<p class="log-title">not available. <span class="stamp"><span >Pinged: </span>Wednesday 1st of January 2014 03:57:03 PM</span></p><p class="log-text"><span data-url="www.examplezz.com">www.examplezz.com - 0 (Timeout)</span><br /><span data-url="www.examplezz.com/othersite">www.examplezz.com/othersite - 0 (Timeout)</span><br /><span data-url="www.idontexist.io">www.idontexist.io - 0 (Timeout)</span><br /><span data-url="www.idontexist.io/othersite">www.idontexist.io/othersite - 0 (Timeout)</span><br /></p>';
var urls = $(data).find('[data-url]').map(function() {
var url = $(this).attr('data-url');
return $('<a>', {href: 'http://' + url})[0].host;
}).get().reduce(function(urls, b) {
if(!(b in urls)) {
urls[b] = 0;
}
urls[b]++;
return urls;
}, {});
console.log(urls);
http://jsbin.com/adEBiCU/5/edit

Categories