How can I get a list of long Wikipedia articles? - wikipedia-api

I know Special:LongPages and I've seen https://en.wikipedia.org/w/api.php and https://en.wikipedia.org/api/rest_v1/.
Is there a way to get long articles (or articles ordered by size) from one of the APIs?

For many special pages, including LongPages, the API equivalent is the querypage module:
let query = {
action: 'query',
list: 'querypage',
qppage: 'Longpages',
format: 'json',
formatversion: 2,
origin: '*'
};
function doQuery( query ) {
return $.get( 'https://en.wikipedia.org/w/api.php', query ).then( function ( data ) {
console.log( data.query.querypage.results.map( function ( item ) {
return item.title;
} ) );
if ( data.continue ) {
let continueQuery = $.extend( {}, query, data.continue );
return doQuery( continueQuery );
}
} );
}
doQuery( query );
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Related

Single dropdown filtering for Datatable

I've been struggling for a few days now, trying to get a single dropdown to filter my table. Upon selection of the eraId, the columns should be refreshed to only show the columns of the selected eraId.
This is how my tables looks like:
I've read a lot of examples on Datatables website or forums but I can't seem to find something working.
I have managed to create a dropdown menu containing the different EraIds as filter (I have simplified the example below with only 3 eraIds) but after selecting an entry in the dropdown, the table gets empty and the column list is not refreshed.
I think the problem is that I first retrieve the columns names, based on the eraId and then draw the table accordingly, displaying only the resources from the specific eraId. I have tried several things but did not manage.
Ideally I should callback getPlayerResourceTable with the selected eraId or update the column list with the resources on the selected eraId.
Javascript:
var columns = [];
function getPlayerResourceTable($selectedEraId) {
$.ajax({
type: "POST",
url: "./graphs.php",
data: { call_function : 'getResourceTableColumns', eraId: $selectedEraId},
success: function (data) {
data = JSON.parse(data);
columnNames = Object.keys(data.data);
for (var i in data.data) {
columns.push({data: data.data[i],
title: data.data[i]});
}
$('#playerResourceTable').DataTable( {
processing: true,
serverSide: false,
filter: true,
columns: columns,
ajax: {
url: './graphs.php',
type: 'POST',
data: { call_function: 'playerResourceTable', column_fields : data.data, eraId: $selectedEraId}
},
initComplete: function () {
this.api().columns( 0 ).every( function () {
var column = this;
var select = $('<select><option value=""></option></select>')
.appendTo( $("#playerResourceTablesWrapper .dataTables_filter"))
.on( 'change', function () {
var val = $.fn.dataTable.util.escapeRegex(
$(this).val()
);
column.search( this.value ).draw();
} );
select.append( '<option value="1">Era 1</option>' )
select.append( '<option value="2">Era 2</option>' )
select.append( '<option value="3">Era 3</option>' )
} );
}
});
}
});
}
$(document).ready(function() {
$selectedEraId = 1;
getPlayerResourceTable($selectedEraId);
} );
PHP:
getResourceTableColumns returns the column list with query similar to SELECT columnName FROM ages WHERE eraId = ?
playerResourceTable returns the resources for each column (type of resource) with query similar to SELECT ".$field_list." FROM user_resources
I also thought of removing WHERE eraId = ? in my MySQL query and filtering the columns on the client side but no luck either.
I eventually ended up separating both functions and destroying/re-creating the table when changing Era.
function getColumns($selectedEraId) {
var columns = [];
$.ajax({
type: "POST",
url: "./graphs.php",
data: { call_function : 'getResourceTableColumns', eraId: $selectedEraId},
success: function (data) {
data = JSON.parse(data);
for (var i in data.data) {
columns.push({data: data.data[i],
title: data.data[i]});
}
if ( $.fn.dataTable.isDataTable( '#playerResourceTable' ) ) { // If the table already exists, detroy it before creating it again
$('#playerResourceTable').DataTable().destroy();
}
getPlayerResourceTable($selectedEraId, columns); // Will recreate the table with the new columns
}
});
}
function getPlayerResourceTable($selectedEraId, columns_to_show) {
$city_id = 91;
$playerResourceTable = $('#playerResourceTable').DataTable( {
processing: true,
serverSide: false,
filter: true,
columns: columns_to_show,
ajax: {
url: './graphs.php',
type: 'POST',
data: { call_function: 'playerResourceTable', column_fields : columns_to_show, city_id : parseInt($city_id)}
},
initComplete: function () {
this.api().columns( 0 ).every( function () {
var column = this;
var select = $('<select id="selectEraId" ><option value=""></option></select>')
.appendTo( $("#playerResourceTablesWrapper .dataTables_filter"))
.on( 'change', function () {
var val = $.fn.dataTable.util.escapeRegex(
$(this).val()
);
column.search( this.value ).draw();
} );
dropdown_string = getEraDropdown($selectedEraId);
} );
$('#selectEraId').on('change', function() {
$selectedEraId = this.value;
columns_to_show = getColumns($selectedEraId);
});
}
});
}

I Can't GroupBy arrays using computed in Vue.js

i want help on this. Thank you.
I have an object :
Funding : [
{person_id:'1';
Amount : '100'},
{person_id:'1';
Amount : '200'},
{person_id:'2';
Amount : '150'},
I would like to groupBy Funding by person_id and get the sum of Amount in each group.
I use this code but nt working ..
Groupe(array,key) {
const result = {}
array.forEach(funding => {
if (!result[funding[person_id]]){
result[funding[person_id]] = []
}
result[funding[person_id]].push(item)
})
return result
}
I created two different examples, one a function will return the summed amount of just one of the keys. In the second, it will return the summed amount of all the keys.
Here is a codepen for that https://codepen.io/aquilesb/pen/BvbqMd
const data = [
{
person_id:'1',
amount : '100'},
{
person_id:'2',
amount : '150'
},
{
person_id:'1',
amount : '150'
},
{
person_id:'2',
amount : '70'
}
];
const personID = '1';
// return by a key
const groupByKey = (list, key) => list.reduce((acc, item) => {
if (item.person_id === key) {
return parseInt(item.amount, 10) + acc;
}
return acc;
}, 0);
//return the sum of all keys
const groupAll = list => list.reduce((acc, item) => {
const accAmout = acc[item.person_id] || 0;
return Object.assign({}, acc, {[item.person_id]: accAmout + parseInt(item.amount, 10)});
}, {});
console.log("groupByKey", groupByKey(data, personID));
console.log("groupAll", groupAll(data));
You can use lodash's .groupBy function and .reduce functions to group by Person ID first, and then add the amounts together. Using a computed property in Vue makes this very easy, and you can access the object in your template like its a regular property.
Vue/HTML Template
<div id="app">
<ul v-for="(total,personId) in fundingByPerson">
<li>Persond ID: {{personId}}, Amount : ${{total.toFixed(2)}}</li>
</ul>
</div>
Javascript
// Include lodash via `npm install lodash`
import _ from 'lodash';
new Vue({
el: "#app",
data() {
return {
Funding: [
{person_id:'1', Amount : '130'},
{person_id:'1', Amount : '200'},
{person_id:'2', Amount : '350'},
{person_id:'45', Amount : '150'}
]
}
},
computed: {
// Group by Person, then add amounts together
fundingByPerson: function(){
let byPerson = _.groupBy(this.Funding, 'person_id');
let totals = {};
// Loop over each Group of Amounts, indexed by personId
_.forEach(byPerson, function(amounts, personId){
totals[personId] = _.reduce( byPerson[personId], function(sum, entry){
return sum + parseFloat( entry.Amount );
}, 0);
})
return totals;
} // fundingByPerson
})
Here's a working fiddle: http://jsfiddle.net/mdy59c7e/6/

Vue.js | Filters is not return

I have a problem.
I am posting a category id with http post. status is returning a data that is true. I want to return with the value count variable from the back. But count does not go back. Return in function does not work. the value in the function does not return from the outside.
category-index -> View
<td>{{category.id | count}}</td>
Controller File
/**
* #Access(admin=true)
* #Route(methods="POST")
* #Request({"id": "integer"}, csrf=true)
*/
public function countAction($id){
return ['status' => 'yes'];
}
Vue File
filters: {
count: function(data){
var count = '';
this.$http.post('/admin/api/dpnblog/category/count' , {id:data} , function(success){
count = success.status;
}).catch(function(error){
console.log('error')
})
return count;
}
}
But not working :(
Thank you guys.
Note: Since you're using <td> it implies that you have a whole table of these; you might want to consider getting them all at once to reduce the amount of back-end calls.
Filters are meant for simple in-place string modifications like formatting etc.
Consider using a method to fetch this instead.
template
<td>{{ categoryCount }}</td>
script
data() {
return {
categoryCount: ''
}
},
created() {
this.categoryCount = this.fetchCategoryCount()
},
methods: {
async fetchCategoryCount() {
try {
const response = await this.$http.post('/admin/api/dpnblog/category/count', {id: this.category.id})
return response.status;
} catch(error) {
console.error('error')
}
}
}
view
<td>{{count}}</td>
vue
data() {
return {
count: '',
}
},
mounted() {
// or in any other Controller, and set your id this function
this.countFunc()
},
methods: {
countFunc: function(data) {
this.$http
.post('/admin/api/dpnblog/category/count', { id: data }, function(
success,
) {
// update view
this.count = success.status
})
.catch(function(error) {
console.log('error')
})
},
},

Accessing a local variable/method within a nested require blocks?

I am not finding in the documentation how to access a local variable of method of the class from within a nested require blocks.
declare( "Clust", StrictIntHashMap,
{
constructor : function()
{
},
cust : function( custId )
{
return this.get( custId );
},
add : function( custObject )
{
this.set( custObject.custId, custObject );
},
reloadThecustses : function()
{
that = this;
require( [ 'inst/DataExtractor', 'inst/ClustTree' ], function ( de, theTree )
{
de.getPlainJSON( Commandz.COMMAND_GET_CUSTS,
function ( dataR )
{
that.add( new Customer( dataR.root[c] ) ); // not working
this.cust( 0 ); // not working
theTree.refreshTheData( dataR.root );
} );
} );
}
} );
return Clust;
How to access the method "add" of the class from within the require block ?
How to access the local variable "that" from within the require block ?
You should be able to access variables defined in the parent scope when using require, since it's equivalent to just having a child scope.
I'm not entirely sure what you are trying to access, but I assume it's the Clust instance.
Would this code work for you?
declare( "Clust", StrictIntHashMap, {
constructor : function() {
},
cust : function( custId ) {
return this.get( custId );
},
add : function( custObject ) {
this.set( custObject.custId, custObject );
},
reloadThecustses : function() {
var clustInstance = this;
require( [ 'inst/DataExtractor', 'inst/ClustTree' ],
function ( de, theTree ) {
de.getPlainJSON( Commandz.COMMAND_GET_CUSTS, function ( dataR ) {
clustInstance.add( new Customer( dataR.root[c] ) );
clustInstance.cust( 0 );
theTree.refreshTheData( dataR.root );
});
});
}
});
return Clust;
Perhaps the problem is caused by having the wrong context in the callback function to getPlainJSON. dojo.hitch() will fix this:
reloadThecustses : function()
{
require( [ 'inst/DataExtractor', 'inst/ClustTree', 'dojo/_base/lang' ], function ( de, theTree, lang )
{
de.getPlainJSON( Commandz.COMMAND_GET_CUSTS,
lang.hitch( function ( dataR )
{
this.add( new Customer( dataR.root[c] ) ); // not working
this.cust( 0 ); // not working
theTree.refreshTheData( dataR.root );
}, this )
} );
}

AutoComplete - yii

I am trying to add a field with auto complete functionality , I have used javascript for this
<link rel="stylesheet" href="http://code.jquery.com/ui/1.9.0/themes/base/jquery-ui.css " />
<script src="http://code.jquery.com/jquery-1.8.2.js "></script>
<script src="http://code.jquery.com/ui/1.9.0/jquery-ui.js "></script>
<script>
$(function() {
var availableTags = [
"ActionScript",
"AppleScript",
"Asp",
"BASIC",
"C",
"C++",
"Clojure",
"COBOL",
"ColdFusion",
"Erlang",
"Fortran",
"Groovy",
"Haskell",
"Java",
"JavaScript",
"Lisp",
"Perl",
"PHP",
"Python",
"Ruby",
"Scala",
"Scheme"
];
function split( val ) {
//document.write(val.length);
return val.split( /,\s*/ );
}
function extractLast( term ) {
//echo (term.length);
//document.write(term.length);
return split( term ).pop();
}
$( "#Tag_tag_name" )
// don't navigate away from the field on tab when selecting an item
.bind( "keydown", function( event ) {
var a=0;
// if (event.keyCode === $.ui.keyCode.TAB)
// {
// a=a+1;
// }
if ( event.keyCode === $.ui.keyCode.TAB &&
$( this ).data( "autocomplete" ).menu.active ) {
event.preventDefault();
}
// if (event.keyCode === $.ui.keyCode.P)
// {
// alert(a);
// }
})
.autocomplete({
minLength: 0,
source: function( request, response ) {
// delegate back to autocomplete, but extract the last term
response( $.ui.autocomplete.filter(
availableTags, extractLast( request.term ) ) );
},
focus: function() {
// prevent value inserted on focus
return false;
},
select: function( event, ui ) {
var terms = split( this.value );
// remove the current input
terms.pop();
// add the selected item
terms.push( ui.item.value );
// add placeholder to get the comma-and-space at the end
terms.push( "" );
this.value = terms.join( ", " );
return false;
}
});
});
</script>
Now What I want tot do is instead of this static values in AvaialbleTags variable I want values from database ? Plus I want to limit three values to be add by the user.
Can anyone help me with this ?
Here is what i am using multicomplete
$this->widget('ext.widgets.MultiComplete', array(
'model'=>$model,
'attribute'=>$attribute,
'splitter'=>',',
'sourceUrl'=>$this->createUrl($url),
// additional javascript options for the autocomplete plugin
'options'=>array(
'minLength'=>'1',
),
'htmlOptions'=>array(
'size'=>'60'
),
));