mirror of https://github.com/adamdruppe/arsd.git
lots of cool stuff
This commit is contained in:
parent
5925ada9a9
commit
2a43ed57bd
5
dom.d
5
dom.d
|
@ -1902,6 +1902,11 @@ class Element {
|
||||||
|
|
||||||
<p>cool <b>api</b> & code dude<p>
|
<p>cool <b>api</b> & code dude<p>
|
||||||
innerText of that is "cool api & code dude".
|
innerText of that is "cool api & code dude".
|
||||||
|
|
||||||
|
This does not match what real innerText does!
|
||||||
|
http://perfectionkills.com/the-poor-misunderstood-innerText/
|
||||||
|
|
||||||
|
It is more like textContent.
|
||||||
*/
|
*/
|
||||||
@property string innerText() const {
|
@property string innerText() const {
|
||||||
string s;
|
string s;
|
||||||
|
|
114
gamehelpers.d
114
gamehelpers.d
|
@ -8,20 +8,43 @@
|
||||||
Usage example:
|
Usage example:
|
||||||
|
|
||||||
---
|
---
|
||||||
class MyGame {
|
final class MyGame : GameHelperBase {
|
||||||
/// Called when it is time to redraw the frame
|
/// Called when it is time to redraw the frame
|
||||||
/// it will try for a particular FPS
|
/// it will try for a particular FPS
|
||||||
final void drawFrame() {
|
override void drawFrame() {
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ACCUM_BUFFER_BIT);
|
||||||
|
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
|
glColor3f(1.0, 1.0, 1.0);
|
||||||
|
glTranslatef(x, y, 0);
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
|
||||||
|
glVertex2i(0, 0);
|
||||||
|
glVertex2i(16, 0);
|
||||||
|
glVertex2i(16, 16);
|
||||||
|
glVertex2i(0, 16);
|
||||||
|
|
||||||
|
glEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
final void update(Duration deltaTime) {
|
int x, y;
|
||||||
|
override void update(Duration deltaTime) {
|
||||||
|
x += 1;
|
||||||
|
y += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override SimpleWindow getWindow() {
|
||||||
|
auto window = create2dWindow("My game");
|
||||||
|
// load textures and such here
|
||||||
|
return window;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
final void fillAudioBuffer(short[] buffer) {
|
final void fillAudioBuffer(short[] buffer) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
@ -45,11 +68,92 @@ public import arsd.color;
|
||||||
public import simpledisplay;
|
public import simpledisplay;
|
||||||
|
|
||||||
import std.math;
|
import std.math;
|
||||||
|
public import core.time;
|
||||||
|
|
||||||
|
public import arsd.joystick;
|
||||||
|
|
||||||
|
SimpleWindow create2dWindow(string title, int width = 512, int height = 512) {
|
||||||
|
auto window = new SimpleWindow(width, height, title, OpenGlOptions.yes);
|
||||||
|
|
||||||
|
window.setAsCurrentOpenGlContext();
|
||||||
|
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
glClearColor(0,0,0,0);
|
||||||
|
glDepthFunc(GL_LEQUAL);
|
||||||
|
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glLoadIdentity();
|
||||||
|
glOrtho(0, width, height, 0, 0, 1);
|
||||||
|
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glLoadIdentity();
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
glEnable(GL_TEXTURE_2D);
|
||||||
|
|
||||||
|
return window;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This is the base class for your game.
|
||||||
|
class GameHelperBase {
|
||||||
|
/// Implement this to draw.
|
||||||
|
abstract void drawFrame();
|
||||||
|
|
||||||
|
/// Implement this to update. The deltaTime tells how much real time has passed since the last update.
|
||||||
|
abstract void update(Duration deltaTime);
|
||||||
|
//abstract void fillAudioBuffer(short[] buffer);
|
||||||
|
|
||||||
|
/// Returns the main game window. This function will only be
|
||||||
|
/// called once if you use runGame. You should return a window
|
||||||
|
/// here like one created with `create2dWindow`.
|
||||||
|
abstract SimpleWindow getWindow();
|
||||||
|
|
||||||
|
|
||||||
|
/// These functions help you handle user input. It offers polling functions for
|
||||||
|
/// keyboard, mouse, joystick, and virtual controller input.
|
||||||
|
///
|
||||||
|
/// The virtual digital controllers are best to use if that model fits you because it
|
||||||
|
/// works with several kinds of controllers as well as keyboards.
|
||||||
|
|
||||||
|
JoystickUpdate joystick1;
|
||||||
|
}
|
||||||
|
|
||||||
/// The max rates are given in executions per second
|
/// The max rates are given in executions per second
|
||||||
/// Redraw will never be called unless there has been at least one update
|
/// Redraw will never be called unless there has been at least one update
|
||||||
void runGame(T)(T game, int maxRedrawRate, int maxUpdateRate) {
|
void runGame(T : GameHelperBase)(T game, int maxUpdateRate = 20, int maxRedrawRate = 0) {
|
||||||
|
// this is a template btw because then it can statically dispatch
|
||||||
|
// the members instead of going through the virtual interface.
|
||||||
|
|
||||||
|
int joystickPlayers = enableJoystickInput();
|
||||||
|
scope(exit) closeJoysticks();
|
||||||
|
|
||||||
|
auto window = game.getWindow();
|
||||||
|
|
||||||
|
window.redrawOpenGlScene = &game.drawFrame;
|
||||||
|
|
||||||
|
auto lastUpdate = MonoTime.currTime;
|
||||||
|
|
||||||
|
window.eventLoop(1000 / maxUpdateRate,
|
||||||
|
delegate() {
|
||||||
|
if(joystickPlayers) {
|
||||||
|
version(linux)
|
||||||
|
readJoystickEvents(joystickFds[0]);
|
||||||
|
auto update = getJoystickUpdate(0);
|
||||||
|
game.joystick1 = update;
|
||||||
|
} else assert(0);
|
||||||
|
|
||||||
|
auto now = MonoTime.currTime;
|
||||||
|
game.update(now - lastUpdate);
|
||||||
|
lastUpdate = now;
|
||||||
|
|
||||||
|
// FIXME: rate limiting
|
||||||
|
window.redrawOpenGlSceneNow();
|
||||||
|
},
|
||||||
|
|
||||||
|
delegate (KeyEvent ke) {
|
||||||
|
// FIXME
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Simple class for putting a TrueColorImage in as an OpenGL texture.
|
/// Simple class for putting a TrueColorImage in as an OpenGL texture.
|
||||||
|
|
20
joystick.d
20
joystick.d
|
@ -171,9 +171,9 @@ version(linux) {
|
||||||
int r = read(fd, &event, event.sizeof);
|
int r = read(fd, &event, event.sizeof);
|
||||||
if(r == -1) {
|
if(r == -1) {
|
||||||
import core.stdc.errno;
|
import core.stdc.errno;
|
||||||
if(errno == EAGAIN || EWOULDBLOCK)
|
if(errno == EAGAIN || errno == EWOULDBLOCK)
|
||||||
break;
|
break;
|
||||||
else assert(0);
|
else assert(0); // , to!string(fd) ~ " " ~ to!string(errno));
|
||||||
}
|
}
|
||||||
assert(r == event.sizeof);
|
assert(r == event.sizeof);
|
||||||
|
|
||||||
|
@ -251,11 +251,23 @@ int enableJoystickInput(
|
||||||
|
|
||||||
int fd = open(filename.ptr, O_RDONLY);
|
int fd = open(filename.ptr, O_RDONLY);
|
||||||
if(fd > 0) {
|
if(fd > 0) {
|
||||||
|
joystickFds[player] = fd;
|
||||||
|
|
||||||
version(with_eventloop) {
|
version(with_eventloop) {
|
||||||
import arsd.eventloop;
|
import arsd.eventloop;
|
||||||
joystickFds[player] = fd;
|
|
||||||
makeNonBlocking(fd);
|
makeNonBlocking(fd);
|
||||||
addFileEventListeners(fd, &readJoystickEvents, null, null);
|
addFileEventListeners(fd, &readJoystickEvents, null, null);
|
||||||
|
} else {
|
||||||
|
// for polling, we will set nonblocking mode anyway,
|
||||||
|
// the readJoystickEvents function will handle this fine
|
||||||
|
// so we can call it when needed even on like a game timer.
|
||||||
|
auto flags = fcntl(fd, F_GETFL, 0);
|
||||||
|
if(flags == -1)
|
||||||
|
throw new Exception("fcntl get");
|
||||||
|
flags |= O_NONBLOCK;
|
||||||
|
auto s = fcntl(fd, F_SETFL, flags);
|
||||||
|
if(s == -1)
|
||||||
|
throw new Exception("fcntl set");
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -855,6 +867,7 @@ version(linux) {
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
version(joystick_demo)
|
||||||
version(linux)
|
version(linux)
|
||||||
void amain(string[] args) {
|
void amain(string[] args) {
|
||||||
import arsd.simpleaudio;
|
import arsd.simpleaudio;
|
||||||
|
@ -945,6 +958,7 @@ version(linux) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
version(joystick_demo)
|
||||||
version(Windows)
|
version(Windows)
|
||||||
void amain() {
|
void amain() {
|
||||||
import arsd.simpleaudio;
|
import arsd.simpleaudio;
|
||||||
|
|
128
jpg.d
128
jpg.d
|
@ -86,3 +86,131 @@ Tuple!(int, int) getSizeFromFile(string filename) {
|
||||||
|
|
||||||
throw new Exception("idk about the length");
|
throw new Exception("idk about the length");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
version(with_libjpeg) {
|
||||||
|
import arsd.color;
|
||||||
|
|
||||||
|
TrueColorImage read_JPEG_file(string filename) {
|
||||||
|
/* This struct contains the JPEG decompression parameters and pointers to
|
||||||
|
* working space (which is allocated as needed by the JPEG library).
|
||||||
|
*/
|
||||||
|
struct jpeg_decompress_struct cinfo;
|
||||||
|
/* We use our private extension JPEG error handler.
|
||||||
|
* Note that this struct must live as long as the main JPEG parameter
|
||||||
|
* struct, to avoid dangling-pointer problems.
|
||||||
|
*/
|
||||||
|
struct my_error_mgr jerr;
|
||||||
|
/* More stuff */
|
||||||
|
FILE * infile; /* source file */
|
||||||
|
JSAMPARRAY buffer; /* Output row buffer */
|
||||||
|
int row_stride; /* physical row width in output buffer */
|
||||||
|
|
||||||
|
/* In this example we want to open the input file before doing anything else,
|
||||||
|
* so that the setjmp() error recovery below can assume the file is open.
|
||||||
|
* VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
|
||||||
|
* requires it in order to read binary files.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((infile = fopen(filename, "rb")) == NULL) {
|
||||||
|
fprintf(stderr, "can't open %s\n", filename);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Step 1: allocate and initialize JPEG decompression object */
|
||||||
|
|
||||||
|
/* We set up the normal JPEG error routines, then override error_exit. */
|
||||||
|
cinfo.err = jpeg_std_error(&jerr.pub);
|
||||||
|
jerr.pub.error_exit = my_error_exit;
|
||||||
|
/* Establish the setjmp return context for my_error_exit to use. */
|
||||||
|
if (setjmp(jerr.setjmp_buffer)) {
|
||||||
|
/* If we get here, the JPEG code has signaled an error.
|
||||||
|
* We need to clean up the JPEG object, close the input file, and return.
|
||||||
|
*/
|
||||||
|
jpeg_destroy_decompress(&cinfo);
|
||||||
|
fclose(infile);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* Now we can initialize the JPEG decompression object. */
|
||||||
|
jpeg_create_decompress(&cinfo);
|
||||||
|
|
||||||
|
/* Step 2: specify data source (eg, a file) */
|
||||||
|
|
||||||
|
jpeg_stdio_src(&cinfo, infile);
|
||||||
|
|
||||||
|
/* Step 3: read file parameters with jpeg_read_header() */
|
||||||
|
|
||||||
|
(void) jpeg_read_header(&cinfo, TRUE);
|
||||||
|
/* We can ignore the return value from jpeg_read_header since
|
||||||
|
* (a) suspension is not possible with the stdio data source, and
|
||||||
|
* (b) we passed TRUE to reject a tables-only JPEG file as an error.
|
||||||
|
* See libjpeg.txt for more info.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Step 4: set parameters for decompression */
|
||||||
|
|
||||||
|
/* In this example, we don't need to change any of the defaults set by
|
||||||
|
* jpeg_read_header(), so we do nothing here.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Step 5: Start decompressor */
|
||||||
|
|
||||||
|
(void) jpeg_start_decompress(&cinfo);
|
||||||
|
/* We can ignore the return value since suspension is not possible
|
||||||
|
* with the stdio data source.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* We may need to do some setup of our own at this point before reading
|
||||||
|
* the data. After jpeg_start_decompress() we have the correct scaled
|
||||||
|
* output image dimensions available, as well as the output colormap
|
||||||
|
* if we asked for color quantization.
|
||||||
|
* In this example, we need to make an output work buffer of the right size.
|
||||||
|
*/
|
||||||
|
/* JSAMPLEs per row in output buffer */
|
||||||
|
row_stride = cinfo.output_width * cinfo.output_components;
|
||||||
|
/* Make a one-row-high sample array that will go away when done with image */
|
||||||
|
buffer = (*cinfo.mem->alloc_sarray)
|
||||||
|
((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
|
||||||
|
|
||||||
|
/* Step 6: while (scan lines remain to be read) */
|
||||||
|
/* jpeg_read_scanlines(...); */
|
||||||
|
|
||||||
|
/* Here we use the library's state variable cinfo.output_scanline as the
|
||||||
|
* loop counter, so that we don't have to keep track ourselves.
|
||||||
|
*/
|
||||||
|
while (cinfo.output_scanline < cinfo.output_height) {
|
||||||
|
/* jpeg_read_scanlines expects an array of pointers to scanlines.
|
||||||
|
* Here the array is only one element long, but you could ask for
|
||||||
|
* more than one scanline at a time if that's more convenient.
|
||||||
|
*/
|
||||||
|
(void) jpeg_read_scanlines(&cinfo, buffer, 1);
|
||||||
|
/* Assume put_scanline_someplace wants a pointer and sample count. */
|
||||||
|
put_scanline_someplace(buffer[0], row_stride);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Step 7: Finish decompression */
|
||||||
|
|
||||||
|
(void) jpeg_finish_decompress(&cinfo);
|
||||||
|
/* We can ignore the return value since suspension is not possible
|
||||||
|
* with the stdio data source.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Step 8: Release JPEG decompression object */
|
||||||
|
|
||||||
|
/* This is an important step since it will release a good deal of memory. */
|
||||||
|
jpeg_destroy_decompress(&cinfo);
|
||||||
|
|
||||||
|
/* After finish_decompress, we can close the input file.
|
||||||
|
* Here we postpone it until after no more JPEG errors are possible,
|
||||||
|
* so as to simplify the setjmp error logic above. (Actually, I don't
|
||||||
|
* think that jpeg_destroy can do an error exit, but why assume anything...)
|
||||||
|
*/
|
||||||
|
fclose(infile);
|
||||||
|
|
||||||
|
/* At this point you may want to check to see whether any corrupt-data
|
||||||
|
* warnings occurred (test whether jerr.pub.num_warnings is nonzero).
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* And we're done! */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
32
minigui.d
32
minigui.d
|
@ -962,7 +962,8 @@ class Window : Widget {
|
||||||
Widget mouseLastOver;
|
Widget mouseLastOver;
|
||||||
Widget mouseLastDownOn;
|
Widget mouseLastDownOn;
|
||||||
override bool dispatchMouseEvent(MouseEvent ev) {
|
override bool dispatchMouseEvent(MouseEvent ev) {
|
||||||
auto ele = widgetAtPoint(this, ev.x, ev.y);
|
auto eleR = widgetAtPoint(this, ev.x, ev.y);
|
||||||
|
auto ele = eleR.widget;
|
||||||
|
|
||||||
if(mouseCapturedBy !is null) {
|
if(mouseCapturedBy !is null) {
|
||||||
if(ele !is mouseCapturedBy && !mouseCapturedBy.isAParentOf(ele))
|
if(ele !is mouseCapturedBy && !mouseCapturedBy.isAParentOf(ele))
|
||||||
|
@ -973,23 +974,30 @@ class Window : Widget {
|
||||||
mouseLastDownOn = ele;
|
mouseLastDownOn = ele;
|
||||||
auto event = new Event("mousedown", ele);
|
auto event = new Event("mousedown", ele);
|
||||||
event.button = ev.button;
|
event.button = ev.button;
|
||||||
|
event.state = ev.modifierState;
|
||||||
|
event.clientX = eleR.x;
|
||||||
|
event.clientY = eleR.y;
|
||||||
event.dispatch();
|
event.dispatch();
|
||||||
} else if(ev.type == 2) {
|
} else if(ev.type == 2) {
|
||||||
auto event = new Event("mouseup", ele);
|
auto event = new Event("mouseup", ele);
|
||||||
event.button = ev.button;
|
event.button = ev.button;
|
||||||
|
event.clientX = eleR.x;
|
||||||
|
event.clientY = eleR.y;
|
||||||
|
event.state = ev.modifierState;
|
||||||
event.dispatch();
|
event.dispatch();
|
||||||
if(mouseLastDownOn is ele) {
|
if(mouseLastDownOn is ele) {
|
||||||
event = new Event("click", ele);
|
event = new Event("click", ele);
|
||||||
event.clientX = ev.x;
|
event.clientX = eleR.x;
|
||||||
event.clientY = ev.y;
|
event.clientY = eleR.y;
|
||||||
event.button = ev.button;
|
event.button = ev.button;
|
||||||
event.dispatch();
|
event.dispatch();
|
||||||
}
|
}
|
||||||
} else if(ev.type == 0) {
|
} else if(ev.type == 0) {
|
||||||
// motion
|
// motion
|
||||||
Event event = new Event("mousemove", ele);
|
Event event = new Event("mousemove", ele);
|
||||||
event.clientX = ev.x;
|
event.state = ev.modifierState;
|
||||||
event.clientY = ev.y;
|
event.clientX = eleR.x;
|
||||||
|
event.clientY = eleR.y;
|
||||||
event.dispatch();
|
event.dispatch();
|
||||||
|
|
||||||
if(mouseLastOver !is ele) {
|
if(mouseLastOver !is ele) {
|
||||||
|
@ -2243,6 +2251,8 @@ class Event {
|
||||||
Key key;
|
Key key;
|
||||||
dchar character;
|
dchar character;
|
||||||
|
|
||||||
|
int state;
|
||||||
|
|
||||||
bool shiftKey;
|
bool shiftKey;
|
||||||
|
|
||||||
private bool isBubbling;
|
private bool isBubbling;
|
||||||
|
@ -2329,18 +2339,24 @@ bool isAParentOf(Widget a, Widget b) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget widgetAtPoint(Widget starting, int x, int y) {
|
struct WidgetAtPointResponse {
|
||||||
|
Widget widget;
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
}
|
||||||
|
|
||||||
|
WidgetAtPointResponse widgetAtPoint(Widget starting, int x, int y) {
|
||||||
assert(starting !is null);
|
assert(starting !is null);
|
||||||
auto child = starting.getChildAtPosition(x, y);
|
auto child = starting.getChildAtPosition(x, y);
|
||||||
while(child) {
|
while(child) {
|
||||||
starting = child;
|
starting = child;
|
||||||
x -= child.x;
|
x -= child.x;
|
||||||
y -= child.y;
|
y -= child.y;
|
||||||
child = starting.widgetAtPoint(x, y);//starting.getChildAtPosition(x, y);
|
child = starting.widgetAtPoint(x, y).widget;//starting.getChildAtPosition(x, y);
|
||||||
if(child is starting)
|
if(child is starting)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return starting;
|
return WidgetAtPointResponse(starting, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
version(win32_theming) {
|
version(win32_theming) {
|
||||||
|
|
2
png.d
2
png.d
|
@ -1230,6 +1230,8 @@ struct LazyPngFile(LazyPngChunksProvider)
|
||||||
return range;
|
return range;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: no longer compiles
|
||||||
|
version(none)
|
||||||
auto byRgbaScanline() {
|
auto byRgbaScanline() {
|
||||||
static struct ByRgbaScanline {
|
static struct ByRgbaScanline {
|
||||||
ReturnType!(rawDatastreamByChunk) datastream;
|
ReturnType!(rawDatastreamByChunk) datastream;
|
||||||
|
|
6
web.d
6
web.d
|
@ -1208,7 +1208,7 @@ void run(Provider)(Cgi cgi, Provider instantiation, size_t pathInfoStartingPoint
|
||||||
cgi.gzipResponse = true;
|
cgi.gzipResponse = true;
|
||||||
cgi.setResponseContentType("text/javascript");
|
cgi.setResponseContentType("text/javascript");
|
||||||
cgi.setCache(true);
|
cgi.setCache(true);
|
||||||
cgi.write(makeJavascriptApi(reflection, replace(cast(string) cgi.requestUri, "functions.js", "")), true);
|
cgi.write(makeJavascriptApi(reflection, replace(cast(string) cgi.pathInfo, "functions.js", "")), true);
|
||||||
cgi.close();
|
cgi.close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -4376,7 +4376,7 @@ enum string javascriptBaseImpl = q{
|
||||||
}
|
}
|
||||||
|
|
||||||
if(method == "POST") {
|
if(method == "POST") {
|
||||||
xmlHttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
|
xmlHttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
|
||||||
a = argString;
|
a = argString;
|
||||||
// adding the CSRF stuff, if necessary
|
// adding the CSRF stuff, if necessary
|
||||||
if(csrfPair.length) {
|
if(csrfPair.length) {
|
||||||
|
@ -4385,7 +4385,7 @@ enum string javascriptBaseImpl = q{
|
||||||
a += csrfPair;
|
a += csrfPair;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
xmlHttp.setRequestHeader("Content-type", "text/plain");
|
xmlHttp.setRequestHeader("Content-Type", "text/plain");
|
||||||
}
|
}
|
||||||
|
|
||||||
xmlHttp.setRequestHeader("X-Requested-With", "XMLHttpRequest");
|
xmlHttp.setRequestHeader("X-Requested-With", "XMLHttpRequest");
|
||||||
|
|
Loading…
Reference in New Issue