I am trying render the plotly.js graph,
For some reason though, the traces.push(this.getTrace(val, calAdjustData)) part seems to be overwriting previous data in the traces array, For every iteration it is returns single value, but finally last value is overwriting all previous values.
destArray.forEach(val=> {
traces.push(this.getTrace(val, calAdjustData));
});
getTrace() function is
getTrace(trace:any, data:any) {
let appConfig: any = [];
appConfig['TABLES'] = {
'R_FORMAT': ',d',
'MONTH_BEGIN_DATE_KEY': 'MONTH_BEGIN_DT',
'CAST_KEYS': [
'DOLLARS_ACTUAL', 'DOLLARS_FORECAST', 'DOLLARS_CALC_FORECAST',
'PY_DOLLARS_ACTUAL', 'PY_DOLLARS_FORECAST', 'PY_DOLLARS_CALC_FORECAST',
'DOLLARS_SUBMITTED', 'PY_DOLLARS_SUBMITTED',
'DOLLARS_ADJ', 'PY_DOLLARS_ADJ',
'DOLLARS_BUDGET', 'NEWNESS_FLAG'
]
};
var traceTmpl:any = Object.assign(this.graphConfig.graphSettings.traceTmpl);
if ("color" in trace) traceTmpl.line.color = trace.color;
if ("dash" in trace) traceTmpl.line.dash = trace.dash;
//traceTmpl.visible = "legendonly";
if ( trace[ "legendgroup" ] ) traceTmpl.legendgroup = trace.legendgroup;
// Compile the trace name for legened and display
traceTmpl.name = trace.label.replace("{type}", this.graphConfig.display.typeLabelMap[this.displaySettings.type]);
traceTmpl.label = trace.label;
if (!(localStorage['legendItems'] =='')) {
let tempArray = JSON.parse(localStorage['legendItems']).filter((x:any)=>x.name.replace("{type}",this.graphConfig.display.typeLabelMap[this.displaySettings.type]) == traceTmpl.name);
if(tempArray && tempArray.length){
traceTmpl.visible = "legendonly"
}
}
// Compile the field name to pluck out of the data array
var field = trace.field.replace("{cal}", this.displaySettings.cal).replace("{type}", this.displaySettings.type);
// Prepare the trace data
traceTmpl.x = _.map(data, appConfig.TABLES.MONTH_BEGIN_DATE_KEY );
traceTmpl.y = _.map(data, field);
// todo: refactor into a function
var tempDate = new Date();
var currentDate = this.getDate( this.displaySettings.currentMonth || [ tempDate.getUTCFullYear(), ( tempDate.getUTCMonth() > 8 ? '':'0' ) + ( tempDate.getUTCMonth() + 1 ), '01' ].join('-') );
if( trace.name.endsWith('actuals') || trace.name.endsWith('actuals_LY') ){
var lastIdx = -1;
traceTmpl.y.forEach( function( val:any, idx:any ) {
if ( val !== 0 ) lastIdx = idx;
} );
for ( let idx = lastIdx + 1; idx < traceTmpl.y.length; ++idx ) traceTmpl.y[ idx ] = void 0;
} else if ( trace.name.endsWith('work_plan')){
var firstIdx = -1;
traceTmpl.y.forEach((val : any, idx :any) => {
var monthCheck = this.getDate( data[idx][ appConfig.TABLES.MONTH_BEGIN_DATE_KEY ] ).getMonth() > currentDate.getMonth();
var yearCheck = this.getDate( data[idx][ appConfig.TABLES.MONTH_BEGIN_DATE_KEY ] ).getUTCFullYear() >= currentDate.getUTCFullYear();
if ( val !== 0 && firstIdx === -1 && ( ( yearCheck && monthCheck ) || this.getDate( data[idx][ appConfig.TABLES.MONTH_BEGIN_DATE_KEY ] ).getUTCFullYear() > currentDate.getUTCFullYear() ) ) {
firstIdx = idx;
}
})
if ( firstIdx !== -1 ){
for ( let idx = 0; idx < firstIdx; ++idx ) traceTmpl.y[idx] = void 0;
}
if ( firstIdx > 0 && trace.altField ){
var altField = trace.altField.replace("{cal}", this.displaySettings.cal).replace("{type}", this.displaySettings.type);
traceTmpl.y[ firstIdx - 1 ] = data[ firstIdx - 1 ][ altField ];
}
} else if ( trace.name == "inventory.forecast" ){
traceTmpl.y.forEach( function ( val:any, idx:any, array:any ) {
if ( val ){
array[ idx ] = val > 0 ? val:0;
}
} );
}
//convert to K dollars as plotly doesn't support that format
//Convert from string to numbers (temporary as DB2 returning strings for some reason) and then convert to K dollars or Units
var denominator = 1000; // K Dollars
if (this.displaySettings.type === "UNITS") denominator = 1;
for (let i in traceTmpl.y) traceTmpl.y[i] = ((+traceTmpl.y[i]) / denominator);
var formatter = d3.format( ( this.displaySettings.type === "DOLLARS" ? '$':'' ) + appConfig.TABLES.R_FORMAT );
traceTmpl.text = traceTmpl.y.map( function ( d:any ){
} );
traceTmpl.text = traceTmpl.y.map((d : any) => {
if ( d || d === 0 ){
return formatter( Math.ceil( d ) );
}else{
return undefined;
}
});
return traceTmpl;
};
Please suggest any solution for this issue, already few similar questions here, but nothing worked for me.
Related
I'm using a Vue Js cryptocurrency chart which displays the latest prices of a list of cryptocurrencies, the problem is that there are a lot of icons links that are broken, but it's not like I can fix them individually, they're all retrieved from a github iconbase. Is there any way I can fix that or at least set a default "No image" icon to show up where there's no icon?
Part responsible for retrieving the icons:
// vue instance
new Vue({
// mount point
el: '#app',
// app data
data: {
endpoint : 'wss://stream.binance.com:9443/ws/!ticker#arr',
iconbase : 'https://raw.githubusercontent.com/rainner/binance-watch/master/public/images/icons/',
cache : {}, // coins data cache
coins : [], // live coin list from api
asset : 'USDT', // filter by base asset pair
search : '', // filter by search string
sort : 'assetVolume', // sort by param
order : 'desc', // sort order ( asc, desc )
limit : 50, // limit list
status : 0, // socket status ( 0: closed, 1: open, 2: active, -1: error )
sock : null, // socket inst
cx : 0,
cy : 0,
},
My full Js:
// common number filters
Vue.filter( 'toFixed', ( num, asset ) => {
if ( typeof asset === 'number' ) return Number( num ).toFixed( asset );
return Number( num ).toFixed( ( asset === 'USDT' ) ? 3 : 8 );
});
Vue.filter( 'toMoney', num => {
return Number( num ).toFixed( 0 ).replace( /./g, ( c, i, a ) => {
return i && c !== "." && ( ( a.length - i ) % 3 === 0 ) ? ',' + c : c;
});
});
// component for creating line chart
Vue.component( 'linechart', {
props: {
width: { type: Number, default: 400, required: true },
height: { type: Number, default: 40, required: true },
values: { type: Array, default: [], required: true },
},
data() {
return { cx: 0, cy: 0 };
},
computed: {
viewBox() {
return '0 0 '+ this.width +' '+ this.height;
},
chartPoints() {
let data = this.getPoints();
let last = data.length ? data[ data.length - 1 ] : { x: 0, y: 0 };
let list = data.map( d => ( d.x - 10 ) +','+ d.y );
this.cx = last.x - 5;
this.cy = last.y;
return list.join( ' ' );
},
},
methods: {
getPoints() {
this.width = parseFloat( this.width ) || 0;
this.height = parseFloat( this.height ) || 0;
let min = this.values.reduce( ( min, val ) => val < min ? val : min, this.values[ 0 ] );
let max = this.values.reduce( ( max, val ) => val > max ? val : max, this.values[ 0 ] );
let len = this.values.length;
let half = this.height / 2;
let range = ( max > min ) ? ( max - min ) : this.height;
let gap = ( len > 1 ) ? ( this.width / ( len - 1 ) ) : 1;
let points = [];
for ( let i = 0; i < len; ++i ) {
let d = this.values[ i ];
let val = 2 * ( ( d - min ) / range - 0.5 );
let x = i * gap;
let y = -val * half * 0.8 + half;
points.push( { x, y } );
}
return points;
}
},
template: `
<svg :viewBox="viewBox" xmlns="http://www.w3.org/2000/svg">
<polyline class="cryptocolor" fill="none" stroke="#fff" stroke-width="2" stroke-linecap="round" :points="chartPoints" />
<circle class="cryptocolor" :cx="cx" :cy="cy" r="4" fill="#fff" stroke="none" />
</svg>`,
});
// vue instance
new Vue({
// mount point
el: '#app',
// app data
data: {
endpoint : 'wss://stream.binance.com:9443/ws/!ticker#arr',
iconbase : 'https://raw.githubusercontent.com/rainner/binance-watch/master/public/images/icons/',
cache : {}, // coins data cache
coins : [], // live coin list from api
asset : 'USDT', // filter by base asset pair
search : '', // filter by search string
sort : 'assetVolume', // sort by param
order : 'desc', // sort order ( asc, desc )
limit : 50, // limit list
status : 0, // socket status ( 0: closed, 1: open, 2: active, -1: error )
sock : null, // socket inst
cx : 0,
cy : 0,
},
// computed methods
computed: {
// process coins list
coinsList() {
let list = this.coins.slice();
let search = this.search.replace( /[^\s\w\-\.]+/g, '' ).replace( /[\r\s\t\n]+/g, ' ' ).trim();
if ( this.asset ) {
list = list.filter( i => i.asset === this.asset );
}
if ( search && search.length > 1 ) {
let reg = new RegExp( '^('+ search +')', 'i' );
list = list.filter( i => reg.test( i.token ) );
}
if ( this.sort ) {
list = this.sortList( list, this.sort, this.order );
}
if ( this.limit ) {
list = list.slice( 0, this.limit );
}
return list;
},
// show socket connection loader
loaderVisible() {
return ( this.status === 2 ) ? false : true;
},
// sort-by label for buttons, etc
sortLabel() {
switch ( this.sort ) {
case 'token' : return 'Token';
case 'percent' : return 'Percent';
case 'close' : return 'Price';
case 'change' : return 'Change';
case 'assetVolume' : return 'Volume';
case 'tokenVolume' : return 'Volume';
case 'trades' : return 'Trades';
default : return 'Default';
}
},
},
// custom methods
methods: {
// apply sorting and toggle order
sortBy( key, order ) {
if ( this.sort !== key ) { this.order = order || 'asc'; }
else { this.order = ( this.order === 'asc' ) ? 'desc' : 'asc'; }
this.sort = key;
},
// filter by asset
filterAsset( asset ) {
this.asset = String( asset || 'BTC' );
},
// set list limit
setLimit( limit ) {
this.limit = parseInt( limit ) || 0;
},
// on socket connected
onSockOpen( e ) {
this.status = 1; // open
console.info( 'WebSocketInfo:', 'Connection open ('+ this.endpoint +').' );
},
// on socket closed
onSockClose( e ) {
this.status = 0; // closed
console.info( 'WebSocketInfo:', 'Connection closed ('+ this.endpoint +').' );
setTimeout( this.sockInit, 10000 ); // try again
},
// on socket error
onSockError( err ) {
this.status = -1; // error
console.error( 'WebSocketError:', err.message || err );
setTimeout( this.sockInit, 10000 ); // try again
},
// process data from socket
onSockData( e ) {
let list = JSON.parse( e.data ) || [];
for ( let item of list ) {
// cleanup data for each coin
let c = this.getCoinData( item );
// keep to up 100 previous close prices in hostiry for each coin
c.history = this.cache.hasOwnProperty( c.symbol ) ? this.cache[ c.symbol ].history : this.fakeHistory( c.close );
if ( c.history.length > 100 ) c.history = c.history.slice( c.history.length - 100 );
c.history.push( c.close );
// add coin data to cache
this.cache[ c.symbol ] = c;
}
// convert cache object to final prices list for each symbol
this.coins = Object.keys( this.cache ).map( s => this.cache[ s ] );
this.status = 2; // active
},
// start socket connection
sockInit() {
if ( this.status > 0 ) return;
try {
this.status = 0; // closed
this.sock = new WebSocket( this.endpoint );
this.sock.addEventListener( 'open', this.onSockOpen );
this.sock.addEventListener( 'close', this.onSockClose );
this.sock.addEventListener( 'error', this.onSockError );
this.sock.addEventListener( 'message', this.onSockData );
}
catch( err ) {
console.error( 'WebSocketError:', err.message || err );
this.status = -1; // error
this.sock = null;
}
},
// start socket connection
sockClose() {
if ( this.sock ) {
this.sock.close();
}
},
// come up with some fake history prices to fill in the initial line chart
fakeHistory( close ) {
let num = close * 0.0001; // faction of current price
let min = -Math.abs( num );
let max = Math.abs( num );
let out = [];
for ( let i = 0; i < 50; ++i ) {
let rand = Math.random() * ( max - min ) + min;
out.push( close + rand );
}
return out;
},
// finalize data for each coin from socket
getCoinData( item ) {
let reg = /^([A-Z]+)(BTC|ETH|BNB|USDT|TUSD)$/;
let symbol = String( item.s ).replace( /[^\w\-]+/g, '' ).toUpperCase();
let token = symbol.replace( reg, '$1' );
let asset = symbol.replace( reg, '$2' );
let name = token;
let pair = token +'/'+ asset;
let icon = this.iconbase + token.toLowerCase() + '_.png';
let open = parseFloat( item.o );
let high = parseFloat( item.h );
let low = parseFloat( item.l );
let close = parseFloat( item.c );
let change = parseFloat( item.p );
let percent = parseFloat( item.P );
let trades = parseInt( item.n );
let tokenVolume = Math.round( item.v );
let assetVolume = Math.round( item.q );
let sign = ( percent >= 0 ) ? '+' : '';
let arrow = ( percent >= 0 ) ? '▲' : '▼';
let info = [ pair, close.toFixed( 8 ), '(', arrow, sign + percent.toFixed( 2 ) +'%', '|', sign + change.toFixed( 8 ), ')' ].join( ' ' );
let style = '';
if ( percent > 0 ) style = 'gain';
if ( percent < 0 ) style = 'loss';
return { symbol, token, asset, name, pair, icon, open, high, low, close, change, percent, trades, tokenVolume, assetVolume, sign, arrow, style, info };
},
// sort an array by key and order
sortList( list, key, order ) {
return list.sort( ( a, b ) => {
let _a = a[ key ];
let _b = b[ key ];
if ( _a && _b ) {
_a = ( typeof _a === 'string' ) ? _a.toUpperCase() : _a;
_b = ( typeof _b === 'string' ) ? _b.toUpperCase() : _b;
if ( order === 'asc' ) {
if ( _a < _b ) return -1;
if ( _a > _b ) return 1;
}
if ( order === 'desc' ) {
if ( _a > _b ) return -1;
if ( _a < _b ) return 1;
}
}
return 0;
});
},
},
// app mounted
mounted() {
this.sockInit();
},
// app destroyed
destroyed() {
this.sockClose();
}
});
Js Fiddle:
https://jsfiddle.net/g5mhe923/1/
My version is from this modification:
https://codepen.io/rainner/pen/bjJYjp
Original source code:
https://github.com/rainner/binance-watch
Js files from the updated version:
https://rainner.github.io/binance-watch/public/bundles/app.min.js
https://rainner.github.io/binance-watch/public/js/crypto-js.min.js
Original demo:
https://rainner.github.io/binance-watch/
Can anyone tell me where I can find a reference to this part?
I couldn't find any reference to this part too:
// app data
data: {
endpoint : 'wss://stream.binance.com:9443/ws/!ticker#arr',
iconbase : 'https://raw.githubusercontent.com/rainner/binance-watch/master/public/images/icons/',
I know 2 tricks for broken link images:
The first is to hide the images with broken link:
<img :src="c.icon" :alt="c.pair" onerror="this.style.display='none'"/>
The second is to use a default image from your choice and display it in case the image link is broken. Like the following where I took one of your images as a default image
<img :src="c.icon" :alt="c.pair" onerror="this.src='https://raw.githubusercontent.com/rainner/binance-watch/master/public/images/icons/xtz_.png'" />
Here is a Demo
I want to display a user-uploaded STL file using Three.js.
My file is sent to the front-end via a GET request: res.sendFile(path). The problem is, I can't use that raw data to load a file without editing Three.js's loader!
Could someone help me edit the STLLoader to accept the result of res.sendFile(path) instead of a path (URL)?
After a week of head-scratching, I've had no luck!
Here's the code of STLLoader.js:
import {
BufferAttribute,
BufferGeometry,
DefaultLoadingManager,
FileLoader,
Float32BufferAttribute,
LoaderUtils,
Vector3
} from "three/build/three.module.js";
var STLLoader = function ( manager ) {
this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
};
STLLoader.prototype = {
constructor: STLLoader,
load: function ( url, onLoad, onProgress, onError ) {
var scope = this;
var loader = new FileLoader( scope.manager );
loader.setPath( scope.path );
loader.setResponseType( 'arraybuffer' );
loader.load( url, function ( text ) {
try {
onLoad( scope.parse( text ) );
} catch ( exception ) {
if ( onError ) {
onError( exception );
}
}
}, onProgress, onError );
},
setPath: function ( value ) {
this.path = value;
return this;
},
parse: function ( data ) {
function isBinary( data ) {
var expect, face_size, n_faces, reader;
reader = new DataView( data );
face_size = ( 32 / 8 * 3 ) + ( ( 32 / 8 * 3 ) * 3 ) + ( 16 / 8 );
n_faces = reader.getUint32( 80, true );
expect = 80 + ( 32 / 8 ) + ( n_faces * face_size );
if ( expect === reader.byteLength ) {
return true;
}
// An ASCII STL data must begin with 'solid ' as the first six bytes.
// However, ASCII STLs lacking the SPACE after the 'd' are known to be
// plentiful. So, check the first 5 bytes for 'solid'.
// Several encodings, such as UTF-8, precede the text with up to 5 bytes:
// https://en.wikipedia.org/wiki/Byte_order_mark#Byte_order_marks_by_encoding
// Search for "solid" to start anywhere after those prefixes.
// US-ASCII ordinal values for 's', 'o', 'l', 'i', 'd'
var solid = [ 115, 111, 108, 105, 100 ];
for ( var off = 0; off < 5; off ++ ) {
// If "solid" text is matched to the current offset, declare it to be an ASCII STL.
if ( matchDataViewAt( solid, reader, off ) ) return false;
}
// Couldn't find "solid" text at the beginning; it is binary STL.
return true;
}
function matchDataViewAt( query, reader, offset ) {
// Check if each byte in query matches the corresponding byte from the current offset
for ( var i = 0, il = query.length; i < il; i ++ ) {
if ( query[ i ] !== reader.getUint8( offset + i, false ) ) return false;
}
return true;
}
function parseBinary( data ) {
var reader = new DataView( data );
var faces = reader.getUint32( 80, true );
var r, g, b, hasColors = false, colors;
var defaultR, defaultG, defaultB, alpha;
// process STL header
// check for default color in header ("COLOR=rgba" sequence).
for ( var index = 0; index < 80 - 10; index ++ ) {
if ( ( reader.getUint32( index, false ) == 0x434F4C4F /*COLO*/ ) &&
( reader.getUint8( index + 4 ) == 0x52 /*'R'*/ ) &&
( reader.getUint8( index + 5 ) == 0x3D /*'='*/ ) ) {
hasColors = true;
colors = new Float32Array( faces * 3 * 3 );
defaultR = reader.getUint8( index + 6 ) / 255;
defaultG = reader.getUint8( index + 7 ) / 255;
defaultB = reader.getUint8( index + 8 ) / 255;
alpha = reader.getUint8( index + 9 ) / 255;
}
}
var dataOffset = 84;
var faceLength = 12 * 4 + 2;
var geometry = new BufferGeometry();
var vertices = new Float32Array( faces * 3 * 3 );
var normals = new Float32Array( faces * 3 * 3 );
for ( var face = 0; face < faces; face ++ ) {
var start = dataOffset + face * faceLength;
var normalX = reader.getFloat32( start, true );
var normalY = reader.getFloat32( start + 4, true );
var normalZ = reader.getFloat32( start + 8, true );
if ( hasColors ) {
var packedColor = reader.getUint16( start + 48, true );
if ( ( packedColor & 0x8000 ) === 0 ) {
// facet has its own unique color
r = ( packedColor & 0x1F ) / 31;
g = ( ( packedColor >> 5 ) & 0x1F ) / 31;
b = ( ( packedColor >> 10 ) & 0x1F ) / 31;
} else {
r = defaultR;
g = defaultG;
b = defaultB;
}
}
for ( var i = 1; i <= 3; i ++ ) {
var vertexstart = start + i * 12;
var componentIdx = ( face * 3 * 3 ) + ( ( i - 1 ) * 3 );
vertices[ componentIdx ] = reader.getFloat32( vertexstart, true );
vertices[ componentIdx + 1 ] = reader.getFloat32( vertexstart + 4, true );
vertices[ componentIdx + 2 ] = reader.getFloat32( vertexstart + 8, true );
normals[ componentIdx ] = normalX;
normals[ componentIdx + 1 ] = normalY;
normals[ componentIdx + 2 ] = normalZ;
if ( hasColors ) {
colors[ componentIdx ] = r;
colors[ componentIdx + 1 ] = g;
colors[ componentIdx + 2 ] = b;
}
}
}
geometry.addAttribute( 'position', new BufferAttribute( vertices, 3 ) );
geometry.addAttribute( 'normal', new BufferAttribute( normals, 3 ) );
if ( hasColors ) {
geometry.addAttribute( 'color', new BufferAttribute( colors, 3 ) );
geometry.hasColors = true;
geometry.alpha = alpha;
}
return geometry;
}
function parseASCII( data ) {
var geometry = new BufferGeometry();
var patternSolid = /solid([\s\S]*?)endsolid/g;
var patternFace = /facet([\s\S]*?)endfacet/g;
var faceCounter = 0;
var patternFloat = /[\s]+([+-]?(?:\d*)(?:\.\d*)?(?:[eE][+-]?\d+)?)/.source;
var patternVertex = new RegExp( 'vertex' + patternFloat + patternFloat + patternFloat, 'g' );
var patternNormal = new RegExp( 'normal' + patternFloat + patternFloat + patternFloat, 'g' );
var vertices = [];
var normals = [];
var normal = new Vector3();
var result;
var groupVertexes = [];
var groupCount = 0;
var startVertex = 0;
var endVertex = 0;
while ( ( result = patternSolid.exec( data ) ) !== null ) {
startVertex = endVertex;
var solid = result[ 0 ];
while ( ( result = patternFace.exec( solid ) ) !== null ) {
var vertexCountPerFace = 0;
var normalCountPerFace = 0;
var text = result[ 0 ];
while ( ( result = patternNormal.exec( text ) ) !== null ) {
normal.x = parseFloat( result[ 1 ] );
normal.y = parseFloat( result[ 2 ] );
normal.z = parseFloat( result[ 3 ] );
normalCountPerFace ++;
}
while ( ( result = patternVertex.exec( text ) ) !== null ) {
vertices.push( parseFloat( result[ 1 ] ), parseFloat( result[ 2 ] ), parseFloat( result[ 3 ] ) );
normals.push( normal.x, normal.y, normal.z );
vertexCountPerFace ++;
endVertex ++;
}
// every face have to own ONE valid normal
if ( normalCountPerFace !== 1 ) {
console.error( 'THREE.STLLoader: Something isn\'t right with the normal of face number ' + faceCounter );
}
// each face have to own THREE valid vertices
if ( vertexCountPerFace !== 3 ) {
console.error( 'THREE.STLLoader: Something isn\'t right with the vertices of face number ' + faceCounter );
}
faceCounter ++;
}
groupVertexes.push( { startVertex: startVertex, endVertex: endVertex } );
groupCount ++;
}
geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
geometry.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
if ( groupCount > 0 ) {
for ( var i = 0; i < groupVertexes.length; i ++ ) {
geometry.addGroup( groupVertexes[ i ].startVertex, groupVertexes[ i ].endVertex, i );
}
}
return geometry;
}
function ensureString( buffer ) {
if ( typeof buffer !== 'string' ) {
return LoaderUtils.decodeText( new Uint8Array( buffer ) );
}
return buffer;
}
function ensureBinary( buffer ) {
if ( typeof buffer === 'string' ) {
var array_buffer = new Uint8Array( buffer.length );
for ( var i = 0; i < buffer.length; i ++ ) {
array_buffer[ i ] = buffer.charCodeAt( i ) & 0xff; // implicitly assumes little-endian
}
return array_buffer.buffer || array_buffer;
} else {
return buffer;
}
}
// start
var binData = ensureBinary( data );
return isBinary( binData ) ? parseBinary( binData ) : parseASCII( ensureString( data ) );
}
};
export { STLLoader };
Some extra info:
The file data, when received by my frontend, looks like this: �u#;�O_?����W�Bt��B���A��B凪B�F�A���BJJ�BȧA�ۢ>#(q>�k?��B
I've been attempting to encode it as an ArrayBuffer using:
var enc = new TextEncoder();
var arrayBuffer = enc.encode(fileString).buffer;
Read the dropped file(s) on the client..
Then change the THREE.DefaultLoadingManager.resolveURL method to convert the requested filenames to return the encoded file contents as Blobs.
Then if you need server upload, at that point, you can kick that off and let it run in the background.
In case this is useful to anyone, I finally solved my problem.
First, I had to fork STLLoader's parse method.
Second, I had run into problems sending and receiving the file, which I solved by explicitly the content type.
On the server, I made sure to explicitly set the content type to 'binary':
app.get("/cube", (req, res) => {
const b = fs.readFileSync("./samples/cube.stl", null);
res.end(b, 'binary');
});
Then, on the client, I set the response type to 'arraybuffer':
import axios from "axios";
import parseSTL from "./lib/parseSTL";
// ...
axios({
method: "get",
url: "/cube",
responseType: "arraybuffer"
}).then(res => {
let geometry = parseSTL(res.data);
});
After that, everything worked as expected!
Alright... My HTML looks like this:
<div id="_content"></div>
And then, there is a method like this:
Main.LoadContent(source, target)
{
var reader = new FileReader();
var s = '';
reader.onload = function()
{
s = reader.result;
var t = $(target).html;
alert(t);
t.html = s;
}
var f = new File([""], source);
reader.readAsText(f);
}
Mind the 'alert(t)' line, it returns:
function ( value ) {
return access( this, function( value ) {
var elem = this[ 0 ] || {},
i = 0,
l = this.length;
if ( value === undefined ) {
return elem.nodeType === 1 ?
elem.innerHTML.replace( rinlinejQuery, "" ) :
undefined;
}
// See if we can take a shortcut and just use innerHTML
if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
( support.htmlSerialize || !rnoshimcache.test( value ) ) &&
( support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&
!wrapMap[ (rtagName.exec( value ) || [ "", "" ])[ 1 ].toLowerCase() ] ) {
value = value.replace( rxhtmlTag, "<$1></$2>" );
try {
for (; i < l; i++ ) {
// Remove element nodes and prevent memory leaks
elem = this[i] || {};
if ( elem.nodeType === 1 ) {
jQuery.cleanData( getAll( elem, false ) );
elem.innerHTML = value;
}
}
elem = 0;
// If using innerHTML throws an exception, use the fallback method
} catch(e) {}
}
if ( elem ) {
this.empty().append( value );
}
}, null, value, arguments.length );
}
The call to Main.LoadContent looks like this:
Main.LoadContent('start.htf', '#_content');
What's my sublime stupidity come to here...???
HTML is a function... put the s variable inside of the function to set the HTML... see what that gets you. Example:
Main.LoadContent(source, target)
{
var reader = new FileReader();
var s = '';
reader.onload = function()
{
s = reader.result;
var t = $(target).html();
alert(t);
//t.html(s);
$(target).html(s);
}
var f = new File([""], source);
reader.readAsText(f);
}
I have a problem with my DataTable. I want to use ColVis plug-in.
My Table is initialised by HTML table - DOM Object.
var colvis = new $.fn.dataTable.ColVis( oTable );
$( colvis.button() ).insertAfter('div.info');
This is how I creating the button, but the button isn't visible. I downloaded full js file (not minimalized) and have following error:
"Uncaught TypeError: Cannot read property 'length' of undefined"
in this function:
"_fnAddButtons": function ()
{
var
nButton,
columns = this.s.dt.aoColumns;
if ( $.inArray( 'all', this.s.aiExclude ) === -1 ) {
for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
{
if ( $.inArray( i, this.s.aiExclude ) === -1 )
{
nButton = this._fnDomColumnButton( i );
nButton.__columnIdx = i;
this.dom.buttons.push( nButton );
}
}
}
if ( this.s.order === 'alpha' ) {
this.dom.buttons.sort( function ( a, b ) {
var titleA = columns[ a.__columnIdx ].sTitle;
var titleB = columns[ b.__columnIdx ].sTitle;
return titleA === titleB ?
0 :
titleA < titleB ?
-1 :
1;
} );
}
if ( this.s.restore )
{
nButton = this._fnDomRestoreButton();
nButton.className += " ColVis_Restore";
this.dom.buttons.push( nButton );
}
if ( this.s.showAll )
{
nButton = this._fnDomShowAllButton();
nButton.className += " ColVis_ShowAll";
this.dom.buttons.push( nButton );
}
$(this.dom.collection).append( this.dom.buttons );
},
he tells that the
columns = this.s.dt.aoColumns;
is undefined.
Can someone help me?
I have the following data and I am wondering how I can match up email1 to password1 and email2 to password2 in this format email:password. I can do it if I do object[0] +":"+ object[1] and object[2] +":"+ object[3] but when the object gets populated with 10 or more items this method is not very efficient. How can I do this with a loop?
I'm using the following code to create the structure:
$("#accounts").on("submit", function(event) {
event.preventDefault();
var form = $(this).serializeArray();
});
You can change the increment in a for loop. Try:
var results = [];
For(var i = 0; i < vals.length; i += 2) {
results.push( { vals[i].value: vals[i+1].value });
}
You can try increment your loop step.
Ref: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Statements?redirectlocale=en-US&redirectslug=JavaScript%2FGuide%2FStatements#for_Statement
Code:
var testMe=new Array({"name":"em1"},{"pwd":"pwd1"},{"name":"em2"},{"pwd":"em2"});
console.log(testMe)
for (var i = 0; i < testMe.length; i+=2) {
console.log(testMe[i].name+"-->"+testMe[i+1].pwd)
}
Demo: http://jsfiddle.net/IrvinDominin/qbVwH/
//
Array.prototype.e = Array.prototype.forEach;
function pair( arr ) {
var len = arr.length;
if ( len ) {
do {
arr.push( arr.splice( 0, 2 ) );
} while ( ( len -= 2 ) >= 2 );
}
return arr;
};
var yourData = [
{ name:"email1", value:"321" },
{ name:"pw1", value:"123" },
{ name:"email2", value:"qwe" },
{ name:"pw2", value:"ewq" },
{ name:"email3", value:"234" },
{ name:"pw3", value:"432" }
],
pairs = {};
pair( yourData )
.e(
function ( P ) {
pairs[ P[0].name ] = P[1].name;
}
);
console.log( pairs );
// Object { email1="pw1", email2="pw2", email3="pw4"}
//