Giter Site home page Giter Site logo

react-swf's Introduction

ReactSWF

Shockwave Flash Player component for React. GCC ADVANCED optimizations compatible.

Supports all browsers supported by React. ReactSWFCompat is required to support IE8-9.

Depends on Object.is() and Object.assign()

Use SWFPlayerVersion to determine SWF Player support.

<ReactSWF
  src="example.swf"
  id="guid_001"
  width="300"
  height="200"
  wmode="transparent"
  flashVars={{foo: 'A', bar: 1}}
/>
const SWF_ID_PREFIX = '__MyExternalInterfaceExample_SWFID_';
const SWF_CALL_NAME_PREFIX = '__MyExternalInterfaceExample_SWFCall_';

let nextUID = 0;

class MyExternalInterfaceExample extends React.Component {
  constructor(props) {
    super(props);

    // For most purposes nextUID is sufficient. However, if you rely on
    // non-trivial server rendering you must generate deterministic UIDs per
    // React root to avoid markup mismatch.
    this._uid = nextUID++;

    window[SWF_CALL_NAME_PREFIX + this._uid] = this.handleSWFCall.bind(this);
  }

  componentWillUnmount() {
    delete window[SWF_CALL_NAME_PREFIX + this._uid];
  }

  handleSWFCall() {
    // Beware; SWF calls are executed in the context of SWF Player.
    console.log('SWFCall', arguments);
    return 'foobar';
  }

  invokeSWFMyCallback(arg) {
    // Beware; SWF Player does not sufficiently escape serialized arguments.
    return this._swfPlayerNode.myCallback(arg);
  }

  render() {
    // Globally unique ID is required for ExternalInterface callbacks in IE<11.
    return (
      <ReactSWF
        ...
        ref={c => this._swfPlayerNode = c}
        id={SWF_ID_PREFIX + this._uid}
        flashVars={{myCallbackName: SWF_CALL_NAME_PREFIX + this._uid}}
      />
    );
  }
}

ReactSWFCompat

ReactSWFCompat (require('react-swf/compat')) also supports IE8-9, but should only be used if you must support these browsers. Internally it uses ReactDOMServer.renderToString to render to markup and then immediately ReactDOM.render on-top of that. There may be some behavioral differences in edge-cases but overall it should behave just the same. Due to the design of React you are required to provide a container element, the SWF-markup will be rendered inside.

<ReactSWFCompat
  container={<div style={{background: '#cccccc'}} />}
  src="example.swf"
  id="guid_001"
  width="300"
  height="200"
  wmode="transparent"
  flashVars={{foo: 'A', bar: 1}}
/>

Breaking changes

1.0.0

  • IE8-9 is no longer supported due to issues with the new DOM renderer in React 15. ReactSWFCompat has been introduced as a workaround to this.

0.13.0

  • getFPVersion and isFPVersionSupported forked to SWFPlayerVersion and dropped from ReactSWF. Replace ReactSWF.getFPVersion => SWFPlayerVersion.get and ReactSWF.isFPVersionSupported => SWFPlayerVersion.isSupported.

0.12.3

0.11.0

  • React 0.13 components no longer support ref.getDOMNode(), use ref.getFPDOMNode() instead.
  • Depends on Object.is(), polyfills are available.

Properties

Standard DOM properties are forwarded to the underlying <object>.

Changes to props cannot be and are not reflected by an already mounted SWF (except for width and height). You must manually provide a computed key to ensure the component is reset when appropriate. Beware, this also applies to src.

src {string} [required]
width {number}
height {number}
flashVars {object|string} - {key: {string}}, "key=value&..."
allowFullScreen {boolean} - true, false*
allowFullScreenInteractive {boolean} - true, false*
allowNetworking {enum} - all*, internal, none
allowScriptAccess {enum} - always, sameDomain*, never
align {enum} - l, t, r
base {string}
bgcolor {string} - #RRGGBB
browserZoom {enum} - scale*, noscale
fullScreenAspectRatio {enum} - portrait, landscape
loop {boolean} - true*, false
menu {boolean} - true*, false
play {boolean} - true*, false
quality {enum} - low, autolow, autohigh, medium, high, best
salign {enum} - l, t, r, tl, tr
scale {enum} - default*, noborder, exactfit, noscale
seamlessTabbing {boolean} - true*, false
wmode {enum} - window*, direct, opaque, transparent, gpu

Detailed explanation of most properties found at [Flash OBJECT and EMBED tag attributes].

API

Instance methods

getFPDOMNode()
  returns {?DOMNode} Flash Player object DOM node.

  Returns the Flash Player object DOM node.
  Should be prefered over `React.findDOMNode`.

AS3 ExternalInterface

Security flaws

Escape object key characters for FP:
"&" => "&amp;"
"<" => "&lt;"
"\"" => "&quot;"

Escape object key characters for JS:
"\r" => "\\r"
"\"" => "\\\""
+ wrap key string with "\""
identifiers with keyword names must also be quoted for JS

Escape string characters for JS:
0x005C => "\\\\" (Backslash)
0x2028 => "\\u2028" (Line separator)
0x2029 => "\\u2029" (Paragraph separator)

Invalid UTF8 characters for FP and JS:
0x0000        (NULL character)
0xD800-0xDFFF (Non private use surrogates)
0xFDD0-0xFDEF (Non-characters)
0xFFFE-0xFFFF (Non-characters)
remove or replace with "\uFFFD" (replacement character)
can only be produced by String.fromCharCode(c) in FP, not "\uXXXX" (exception: 0x0000)

This list may be incomplete.

ExternalInterface.addCallback

Returned strings should be encoded using StringForJS.encode.

You must provide a unique DOM id to ReactSWF for IE8-10.

<ReactSWF id="my_guid_123" ... />

ExternalInterface.call

String arguments should be encoded using StringForJS.encode.

StringForJS.encode

The Flash run-time does not sufficiently encode strings passed to JavaScript. This can cause run-time errors, string corruption or character substitution to occur. Encoded strings are transparently decoded by the JavaScript run-time.

public class StringForJS {
  private static var UNSAFE_CHARS_REGEX:RegExp = new RegExp(
    // NULL-char (0x00) and backslash (0x5C)
    "[\\x00\\\\" +
    // Line separator (0x2028), paragraph separator (0x2029)
    "\u2028-\u2029" +
    // Non private use surrogates (0xD800 - 0xDFFF)
    String.fromCharCode(0xD800) + "-" + String.fromCharCode(0xDFFF) +
    // Non-characters (0xFDD0 - 0xFDEF)
    String.fromCharCode(0xFDD0) + "-" + String.fromCharCode(0xFDEF) +
    // Non-characters (0xFFFE + 0xFFFF)
    String.fromCharCode(0xFFFE) + String.fromCharCode(0xFFFF) + "]",
    "g"
  );

  private static function unsafeCharEscaper():String {
    switch (arguments[0]) {
      case "\u0000": return "\\0";
      case "\u005C": return "\\\\";
      case "\u2028": return "\\u2028";
      case "\u2029": return "\\u2029";
      default:       return "\uFFFD";
    };
  }

  // Encode unsafe strings for use with ExternalInterface. Invalid characters
  // are substituted by the Unicode replacement character.
  public static function encode(value:String):String {
    return value.replace(UNSAFE_CHARS_REGEX, unsafeCharEscaper);
  }
}

react-swf's People

Contributors

syranide avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

react-swf's Issues

Not Triggering Firefox ExternalInterface Callback

I'm not sure of the best way to get you a minimal example to demo this, but embedding a Flash movie in Firefox doesn't seem to trigger ExternalInterface callbacks, nor can I call exposed methods from the Flash movie.

The SWF I'm using is from here: https://github.com/mangui/flashls/blob/dev/bin/debug/flashlsChromeless.swf

I have a component with the following relevant methods:

componentWillMount() {
    window.VideoPlayer = window.VideoPlayer || {};
    window.VideoPlayer[this.props.video.id] = {
        callback: _.bind(this.flashCallback, this)
    };
}

componentDidMount() {
    this.$plugin = this.refs.flash.getFPDOMNode();
}

render() {
    let vars = {
        callback: `window.VideoPlayer[${this.props.video.id}].callback`
    };

    return (
        <ReactSWF
            allowScriptAccess="always"
            flashVars={ vars }
            id={ `videoPlayer_${this.props.video.id}` }
            key={ `videoPlayer_${this.props.video.id}` }
            ref="flash"
            src="/assets/flash/VideoPlayer.swf"
            wmode="transparent"
        />
    );
}

flashCallback(event, args) {
    this.log.debug({ args }, `Flash Player :: ${event}`);

    if (_.isFunction(this[`on${eventName}`])) {
        this[`on${eventName}`].apply(this, args);
    }
}

This all works correctly in Chrome at the very least. Firefox doesn't seem to ever call the callback, nor can I call this.$plugin.methodOnFlashMovie() like I would expect.

Update SWF Object

Hi.

So if I want to refresh ReactSWF, I should provide new key property?
Because changing of FlashVars doesn't do anything ;)

Something like this:

render: function () {
            var key = keyIndex++;
            return (
                <div className="player">
                    <ReactSWF
                        key={key}
                        src={this.props.swfUrl}
                        id="hdsPlayer"
                        width={this.state.componentWidth}
                        height={this.state.componentHeight}
                        wmode="transparent"
                        flashVars={this.props.flashVars}/>
                </div>
            );
        }

Because React v16 remove React.PropTypes, react-swf does't work well

When i update react v16, i see this

The deprecations introduced in 15.x have been removed from the core package. 
React.createClass is now available as create-react-class, React.PropTypes as prop-types, 
React.DOM as react-dom-factories, react-addons-test-utils as react-dom/test-utils,
and shallow renderer as react-test-renderer/shallow. See 15.5.0 and 15.6.0 blog posts for 
instructions on migrating code and automated codemods.

So it not work as below:

var PropTypes = React.PropTypes;
ReactSWFCompat.propTypes = {
  container: PropTypes.element.isRequired
};

Plz update PropTypes that depends on 'prop-types'

Can't interact with SWF

I really have the simplest possible example. SWF shows, but I can't click anything on it. Any ideas?

import React, { Component } from 'react';
import './App.css';
import ReactSWF from 'react-swf'

class App extends Component {
  render() {
    return (
      <div className="App">
        <ReactSWF
          src="MFD1.swf"
          id="mfd1"
          width="500"
          height="700"
          wmode="transparent"
        // flashVars={{ foo: 'A', bar: 1 }}
        />
      </div>
    );
  }
}

export default App;

"ReferenceError: React is not defined" when building with browserify.

A distilled example can be found here: https://github.com/sesm/reactswf-build-issue
To reproduce the issue:

$npm install
$npm run build
Open main.html in browser

Expected: tag appears on the page.
Observed: "ReferenceError: React is not defined" in JS console.

This issue can be fixed by adding a line

var React=require('react');

to the top of react-swf.js, but I'm not sure it's the right way to fix the problem since I'm not yet familiar enough with NPM module system.

Call function from Flash

I want call javascript function from Flash.
I use ExternalInterface in flash action as:

ExternalInterface.call("buttonClicked", buttonNumber);

but where should I put the function buttonClicked in the react and how it get the variable ButtonNumber in react?

Please explain and give us any simple example.
it will be very helpful.

many thanks

call js function with context

Hello. Thanks for great component!

I have a problem with calling js callback function in context of my parent component:

import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import ReactSWF from 'react-swf';

import './style.sass';

class Player extends Component {
    static propTypes = {
        url: PropTypes.string.isRequired,
        style: PropTypes.shape({
            position: PropTypes.oneOf([
                'absolute',
                'fixed'
            ]).isRequired,
            top: PropTypes.string,
            left: PropTypes.string,
            bottom: PropTypes.string,
            right: PropTypes.string,
            width: PropTypes.string.isRequired,
            height: PropTypes.string.isRequired
        }).isRequired
    };

    constructor(props) {
        super(props);
    }

    onJSBridge(...args) {
        console.log(this);
        console.log(args);
    }

    render() {
        const { style } = this.props;

        return (
            <div className="player-container" style={style}>
                <ReactSWF
                    src={'/player/GrindPlayer.swf'}
                    id={'player'}
                    ref={'player'}
                    name={'player'}
                    width={style.width}
                    height={style.height}
                    wmode={'transparent'}
                    flashVars={{javascriptCallbackFunction: this.onJSBridge}} />
            </div>
        );
    }
}

const select = state => state.player;

export default connect(select)(Player);

method onJSBridge allways call in window context. But if I pass flashVars={{javascriptCallbackFunction: this.onJSBridge.bind(this)}} I see error:

Uncaught SyntaxError: Unexpected identifier in console

How could I call method of object?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.