Code Monkey home page Code Monkey logo

nova-froala-field's Introduction

Nova Froala Field

Froala WYSIWYG Editor field for Laravel Nova

Latest Version on Packagist Build Status Code Style Status Total Downloads

Introduction

Froala WYSIWYG Editor Field

Full support of attaching Images, Files and Videos

Form Field

Notifications for Froala events are handled by Toasted which is provided in Nova by default.

Upgrading

For upgrading to Froala 3, check out โ€“ Upgrading Instructions.

Installation

You can install the package into a Laravel application that uses Nova via composer:

composer require froala/nova-froala-field

Usage

Just use the Froala\NovaFroalaField\Froala field in your Nova resource:

namespace App\Nova;

use Froala\NovaFroalaField\Froala;

class Article extends Resource
{
    // ...

    public function fields(Request $request)
    {
        return [
            // ...

            Froala::make('Content'),

            // ...
        ];
    }
}

Override Config Values

To change any of config values for froala field, publish a config file:

php artisan vendor:publish --tag=config --provider=Froala\\NovaFroalaField\\FroalaFieldServiceProvider

Customize Editor Options

For changing any Available Froala Option edit nova.froala-field.options value:

/*
|--------------------------------------------------------------------------
| Default Editor Options
|--------------------------------------------------------------------------
|
| Setup default values for any Froala editor option.
|
| To view a list of all available options check out the Froala documentation
| {@link https://www.froala.com/wysiwyg-editor/docs/options}
|
*/

'options' => [
    'toolbarButtons' => [
        [
            'bold',
            'italic',
            'underline',
        ],
        [
            'formatOL',
            'formatUL',
        ],
        [
            'insertImage',
            'insertFile',
            'insertLink',
            'insertVideo',
        ],
        [
            'embedly',
            'html',
        ],
    ],
],

//...

If you want to set options only to specific field, just pass them to options method:

public function fields(Request $request)
{
    return [
        // ...

        Froala::make('Content')->options([
            'editorClass' => 'custom-class',
            'height' => 300,
        ]),

        // ...
    ];
}

Attachments

Nova Froala Field provides native attachments driver which works similar to Trix File Uploads, but with ability to optimize images and preserve file names. Also you have an ability to switch to the trix driver to use its upload system.

  • It's Recommended to use froala driver (enabled by default) to be able to use current and future additional features for attachments, provided by Froala.

Froala Driver

To use froala driver, publish and run a migration:

php artisan vendor:publish --tag=migrations --provider=Froala\\NovaFroalaField\\FroalaFieldServiceProvider 
php artisan migrate

Trix Driver

If previously you have used Trix attachments and you want to preserve behavior with same tables and handlers you can use trix driver in config file:

/*
|--------------------------------------------------------------------------
| Editor Attachments Driver
|--------------------------------------------------------------------------
|
| If you have used `Trix` previously and want to save the same flow with
| `Trix` attachments handlers and database tables you can use
| "trix" driver.
|
| *** Note that "trix" driver doesn't support image optimization
| and file names preservation.
|
| It is recommended to use "froala" driver to be able to automatically
| optimize uploaded images and preserve attachments file names.
|
| Supported: "froala", "trix"
|
*/

'attachments_driver' => 'trix'

//...

Attachments Usage

To allow users to upload images, files and videos, just like with Trix field, chain the withFiles method onto the field's definition. When calling the withFiles method, you should pass the name of the filesystem disk that photos should be stored on:

use Froala\NovaFroalaField\Froala;

Froala::make('Content')->withFiles('public');

And also, in your app/Console/Kernel.php file, you should register a daily job to prune any stale attachments from the pending attachments table and storage:

use Froala\NovaFroalaField\Jobs\PruneStaleAttachments;


/**
* Define the application's command schedule.
*
* @param  \Illuminate\Console\Scheduling\Schedule  $schedule
* @return void
*/
protected function schedule(Schedule $schedule)
{
    $schedule->call(function () {
        (new PruneStaleAttachments)();
    })->daily();
}

Filenames Preservation

A unique ID is generated by default to serve as the file name according to store method specification. If you want to preserve original client filenames for uploaded attachments, change preserve_file_names option in config file to true.

/*
|--------------------------------------------------------------------------
| Preserve Attachments File Name
|--------------------------------------------------------------------------
|
| Ability to preserve client original file name for uploaded
| image, file or video.
|
*/

'preserve_file_names' => true,

//...

Images Optimization

All uploaded images will be optimized by default by spatie/image-optimizer.

You can disable image optimization in config file:

/*
|--------------------------------------------------------------------------
| Automatically Images Optimization
|--------------------------------------------------------------------------
|
| Optimize all uploaded images by default.
|
*/

'optimize_images' => false,

//...

Or set custom optimization options for any optimizer:

/*
|--------------------------------------------------------------------------
| Image Optimizers Setup
|--------------------------------------------------------------------------
|
| These are the optimizers that will be used by default.
| You can setup custom parameters for each optimizer.
|
*/

'image_optimizers' => [
    Spatie\ImageOptimizer\Optimizers\Jpegoptim::class => [
        '-m85', // this will store the image with 85% quality. This setting seems to satisfy Google's Pagespeed compression rules
        '--strip-all', // this strips out all text information such as comments and EXIF data
        '--all-progressive', // this will make sure the resulting image is a progressive one
    ],
    Spatie\ImageOptimizer\Optimizers\Pngquant::class => [
        '--force', // required parameter for this package
    ],
    Spatie\ImageOptimizer\Optimizers\Optipng::class => [
        '-i0', // this will result in a non-interlaced, progressive scanned image
        '-o2', // this set the optimization level to two (multiple IDAT compression trials)
        '-quiet', // required parameter for this package
    ],
    Spatie\ImageOptimizer\Optimizers\Svgo::class => [
        '--disable=cleanupIDs', // disabling because it is known to cause troubles
    ],
    Spatie\ImageOptimizer\Optimizers\Gifsicle::class => [
        '-b', // required parameter for this package
        '-O3', // this produces the slowest but best results
    ],
],

Image optimization currently supported only for local filesystems

Upload Max Filesize

You can set max upload filesize for attachments. If set to null, max upload filesize equals to php.ini upload_max_filesize directive value.

/*
|--------------------------------------------------------------------------
| Maximum Possible Size for Uploaded Files
|--------------------------------------------------------------------------
|
| Customize max upload filesize for uploaded attachments.
| By default it is set to "null", it means that default value is
| retrieved from `upload_max_size` directive of php.ini file.
|
| Format is the same as for `uploaded_max_size` directive.
| Check out FAQ page, to get more detail description.
| {@link http://php.net/manual/en/faq.using.php#faq.using.shorthandbytes}
|
*/

'upload_max_filesize' => null,

//...

Display Edited Content

According to Froala Display Edited Content documentation you should publish Froala styles:

php artisan vendor:publish --tag=froala-styles --provider=Froala\\NovaFroalaField\\FroalaFieldServiceProvider 

include into view where an edited content is shown:

<!-- CSS rules for styling the element inside the editor such as p, h1, h2, etc. -->
<link href="{{ asset('css/vendor/froala_styles.min.css') }}" rel="stylesheet" type="text/css" />

Also, you should make sure that you put the edited content inside an element that has the .fr-view class:

<div class="fr-view">
    {!! $article->content !!}
</div>

Show on Index Page

You have an ability to show field content on resource index page in popup window:

use Froala/NovaFroalaField/Froala;

Froala::make('Content')->showOnIndex();

Just click Show Content

Index Field

License Key

To setup your license key, uncomment key option in the config file and set FROALA_KEY environment variable

// ...
'options' => [
    'key' => env('FROALA_KEY'),
    // ...
],

3rd Party Integrations

To enable a button that uses some a 3rd party service and needs additional script including, like: Embed.ly, TUI Advanced Image Editor or SCAYT Web SpellChecker, you should publish 3rd party scripts:

php artisan vendor:publish --tag=nova-froala-field-plugins --provider=Froala\\NovaFroalaField\\FroalaFieldServiceProvider

Script will be dynamically imported when you enable embedly or spellChecker buttons.

TUI Advanced Image Editor

If you want to use TUI Image Editor to add advanced image editing options, switch tuiEnable option to true:

'options' => [
    // 'key' => env('FROALA_KEY'),

    // 'tuiEnable' => true,

    //...
],

Font Awesome 5

If you have a Font Awesome Pro license, you can enable using the regular icons instead of the solid ones by using the iconsTemplate option.

Add iconsTemplate config value into froala-field.php config:

'options' => [
    // 'key' => env('FROALA_KEY'),

   'iconsTemplate' => 'font_awesome_5',
   // If you want to use the regular/light icons, change the template to the following.
   // iconsTemplate: 'font_awesome_5r'
   // iconsTemplate: 'font_awesome_5l'
   
   //...
],

Note:

If you have any problems with loading 3rd party plugins, try to republish it

php artisan vendor:publish --tag=nova-froala-field-plugins --force

Advanced

Custom Event Handlers

If you want to setup custom event handlers for froala editor instance, create js file and assign events property to window.froala:

window.froala = {
    events: {
        'image.error': (error, response) => {},
        'imageManager.error': (error, response) => {},
        'file.error': (error, response) => {},
    }
};

to all callbacks provided in window.froala.events, the context of VueJS form field component is automatically applied, you can work with this inside callbacks like with Vue instance component.

After that, load the js file into Nova scripts in NovaServiceProvider::boot method:

public function boot()
{
    parent::boot();

    Nova::serving(function (ServingNova $event) {
        Nova::script('froala-event-handlers', public_path('path/to/js/file.js'));
    });
}

Customize Attachment Handlers

You can change any of attachment handlers by passing a callable:

use App\Nova\Handlers\{
    StorePendingAttachment,
    DetachAttachment,
    DeleteAttachments,
    DiscardPendingAttachments,
    AttachedImagesList
};

Froala::make('Content')
    ->attach(new StorePendingAttachment)
    ->detach(new DetachAttachment)
    ->delete(new DeleteAttachments)
    ->discard(new DiscardPendingAttachments)
    ->images(new AttachedImagesList)

Testing

composer test

Changelog

Please see CHANGELOG for more information on what has changed recently.

Contributing

Please see CONTRIBUTING for details.

Security

If you discover any security related issues, please email [email protected] instead of using the issue tracker.

Credits

License

The MIT License (MIT). Please see License File for more information.

nova-froala-field's People

Contributors

clingle avatar shaffe-fr avatar spekulatius avatar sytheveenje avatar tharindu-abans 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  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  avatar  avatar

nova-froala-field's Issues

Customize Attachment Handlers Throws error

When trying to implement a Customize Attachment Handler the same way the example is shown in the docs, an error is thrown due to the lack of Field being passed in. However, you're unable to pass the Froala $field to the class from the Nova Resource.

Do you have any recommendations for this?

Froala::make('description')
    ->attach(new StorePendingMedia)
    ->detach(new DetachMedia)
    ->delete(new DeleteMedia)
     ->discard(new DiscardPendingMedia)
     ->images(new AttachedMediasList)
     ->options([
             'toolbarBottom'=>true,
             'height' => 400
     ]),

404 on JSON field

I have Froala working via a JSON column in MYSQL and Froala is throwing a 404 when trying to upload to that JSON column. http://laravel.test/nova-vendor/froala-field/pages/image-manager?field=content->features->features_description

Error uploading files when using a port on the URL

Hi,

Great work first of all! Congratulations!

The issue is simple: If I use a port on the url, on my case "localhost:8000" the "link" value on the returned ajax json called from the "nova-vendor/froala-field/posts/attachments/body" doesn't show the url.

Steps to reproduce:

Start a webserver with a port. You can use the default 8000 when running "php artisan serve".

Try to upload an image:
image

Then you can see the "link" value is wrong:
image

I dug up the code and the StorePendingAttachment class looks like it's working correctly. Still, the line:
Storage::disk($this->field->disk)->url($attachment)
is not showing the right url somehow ...

Hope it helps!
Bruno.

No Issue

No issue, I just want to say I LOVE this and it's been working amazingly for me. Please keep up the amazing work and thank you. Sorry, just didn't know where else I could post this. Best Nova package ever!

Missing toolbar buttons

Just installed this package and published the config file. Now I am wondering why there is only a </> button in the toolbar. I have not changed anything in the config file and as I understand it should list all buttons from this array. Also it might be a good idea to give directions to where you expect to find the font-awesome icons. Seems to be not working :)

'toolbarButtons' => [
            [
                '|',
                'bold',
                'italic',
                'underline',
            ],
            [
                'formatOL',
                'formatUL',
            ],
            [
                'insertImage',
                'insertFile',
                'insertLink',
                'insertVideo',
            ],
            [
                'html',
            ],
        ],

Loading language files

You can choose any language to nova-froala-field at config, but what's the best way to include language files (ex - ru.js)? They don't seem to be included into package.

Interger & Float error

novaerror1
That's the error message I am getting, immediately after installing the package. What could I be doing wrong?

Issue with "/" key

I'm using MacOS 10.14, tested on Firefox and Chrome, both have this issue. When I try to type "/" or "?" on Froala editor, it'll automatically update the typing focus to the Nova search bar (at the top bar).

Paragraphs within editor with no space between them

Hello,

The html code of the content I have entered into Froala is the following:

<p>Hello</p>

<p>New paragraph</p>

However, within the editor there is no space between the paragraphs:
Screenshot 2019-07-25 at 12 03 06

I have not made any changes to the default options, rather than adding
'entities' => '&quot;&#39;&iexcl;&cent;&pound;&curren;&yen;&brvbar;',

Thank you.

Events firing when editor loads

Hello,

I am using Froala in a Laravel application, utilising Nova and nova-froala-field package.

Following the instructions of nova-froala-field, I have created a .js file containing my event handlers:

window.froala = {
    events: {
        'image.inserted': ($img, response) => {
            console.log('inserted');
        }
    }
};

And then loaded this file in NovaServiceProvider::boot method:

Nova::serving(function (\Laravel\Nova\Events\ServingNova $event) {
   Nova::script('froala-event-handlers', public_path('js/froala-event-handlers.js'));
});

So far so good, when an image is inserted in the editor, the event is fired.
However, the event is also "automatically" fired when the page firstly loads. The same happens for image.loaded and image.error events.
Is this the expected behaviour?

Thank you,
Ilias

How can I use blockquote?

I've tried to use in Froala::make('Content')->options with some plugins with this option like "codeBeautifier" but doesn't work. Someone could help me wit this question?

Working with S3

Trying to upload or list images on S3, I've set the ->withFiles('s3') but still nothing... aparently the path is not found

message: "The file "pa/xxx.jpg" does not exist",โ€ฆ

How to make use of plugin options such as linkAlwaysBlank

Hi,

I am using the Frola editor and I would like to define some options such as linkAlwaysBlank or linkAlwaysNoFollow. The problem is I haven't found anything about it in the nova documentation. How can I do this?

Also, how can I add custom values to the rel attribute such as noopener as default?

Kind regards!

Embedly button not diplayed after upgrade to v3.0

Hey! Great plugin, however after the recent upgrade from v2.2.1 to v3.0 the Embed.ly button is no longer displayed. I updated the app/config/nova/froala-field.php toolbarButtons array according to the upgrading instructions but for some reason it's not displaying the Embed.ly button even though I have it in my config:

'options' => [
        // 'key' => env('FROALA_KEY'),

        'iconsTemplate' => 'font_awesome_5',

        'tuiEnable' => true,

        'toolbarButtons' => [
            [
                'bold',
                'italic',
                'underline',
            ],
            [
                'formatOL',
                'formatUL',
            ],
            [
                'insertImage',
                'insertFile',
                'insertLink',
                'insertVideo',
                'embedly',
            ],
            [
                'html',
            ]
        ],
    ],

proc_open error when uploading an image

Hi,

The editor is working, except image upload. I ran the migrations, but after uploading a file, I get an error:

Symfony\Component\Process\Exception\LogicException: The Process class relies on proc_open, which is not available on your PHP installation. in file /customers/c/e/1/jens/httpd.private/vendor/symfony/process/Process.php on line 143

#0 /customers/c/e/1/jens/httpd.private/vendor/symfony/process/Process.php(195): Symfony\Component\Process\Process->__construct(Array, NULL, NULL, NULL, 60)
#1 /customers/c/e/1/jens/httpd.private/vendor/spatie/image-optimizer/src/OptimizerChain.php(97): Symfony\Component\Process\Process::fromShellCommandline('"jpegoptim" -m8...')
#2 /customers/c/e/1/jens/httpd.private/vendor/spatie/image-optimizer/src/OptimizerChain.php(77): Spatie\ImageOptimizer\OptimizerChain->applyOptimizer(Object(Spatie\ImageOptimizer\Optimizers\Jpegoptim), Object(Spatie\ImageOptimizer\Image))
#3 /customers/c/e/1/jens/httpd.private/vendor/froala/nova-froala-field/src/Handlers/StorePendingAttachment.php(87): Spatie\ImageOptimizer\OptimizerChain->optimize('/customers/c/e/...')
#4 /customers/c/e/1/jens/httpd.private/vendor/froala/nova-froala-field/src/Handlers/StorePendingAttachment.php(53): Froala\NovaFroalaField\Handlers\StorePendingAttachment->imageOptimize('TgaIUKWHgfny57B...')
#5 [internal function]: Froala\NovaFroalaField\Handlers\StorePendingAttachment->__invoke(Object(Laravel\Nova\Http\Requests\NovaRequest))
#6 /customers/c/e/1/jens/httpd.private/vendor/froala/nova-froala-field/src/Http/Controllers/FroalaUploadController.php(25): call_user_func(Object(Froala\NovaFroalaField\Handlers\StorePendingAttachment), Object(Laravel\Nova\Http\Requests\NovaRequest))
#7 [internal function]: Froala\NovaFroalaField\Http\Controllers\FroalaUploadController->store(Object(Laravel\Nova\Http\Requests\NovaRequest), 'pages', 'content')
#8 /customers/c/e/1/jens/httpd.private/vendor/laravel/framework/src/Illuminate/Routing/Controller.php(54): call_user_func_array(Array, Array)
#9 /customers/c/e/1/jens/httpd.private/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php(45): Illuminate\Routing\Controller->callAction('store', Array)
#10 /customers/c/e/1/jens/httpd.private/vendor/laravel/framework/src/Illuminate/Routing/Route.php(219): Illuminate\Routing\ControllerDispatcher->dispatch(Object(Illuminate\Routing\Route), Object(Froala\NovaFroalaField\Http\Controllers\FroalaUploadController), 'store')
#11 /customers/c/e/1/jens/httpd.private/vendor/laravel/framework/src/Illuminate/Routing/Route.php(176): Illuminate\Routing\Route->runController()
#12 /customers/c/e/1/jens/httpd.private/vendor/laravel/framework/src/Illuminate/Routing/Router.php(681): Illuminate\Routing\Route->run()
#13 /customers/c/e/1/jens/httpd.private/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(130): Illuminate\Routing\Router->Illuminate\Routing{closure}(Object(Illuminate\Http\Request))
#14 /customers/c/e/1/jens/httpd.private/nova/src/Http/Middleware/Authorize.php(18): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(Object(Illuminate\Http\Request))
#15 /customers/c/e/1/jens/httpd.private/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(171): Laravel\Nova\Http\Middleware\Authorize->handle(Object(Illuminate\Http\Request), Object(Closure))
#16 /customers/c/e/1/jens/httpd.private/nova/src/Http/Middleware/BootTools.php(20): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(Object(Illuminate\Http\Request))
#17 /customers/c/e/1/jens/httpd.private/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(171): Laravel\Nova\Http\Middleware\BootTools->handle(Object(Illuminate\Http\Request), Object(Closure))
#18 /customers/c/e/1/jens/httpd.private/nova/src/Http/Middleware/DispatchServingNovaEvent.php(20): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(Object(Illuminate\Http\Request))
#19 /customers/c/e/1/jens/httpd.private/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(171): Laravel\Nova\Http\Middleware\DispatchServingNovaEvent->handle(Object(Illuminate\Http\Request), Object(Closure))
#20 /customers/c/e/1/jens/httpd.private/vendor/laravel/framework/src/Illuminate/Auth/Middleware/Authenticate.php(43): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(Object(Illuminate\Http\Request))
#21 /customers/c/e/1/jens/httpd.private/nova/src/Http/Middleware/Authenticate.php(31): Illuminate\Auth\Middleware\Authenticate->handle(Object(Illuminate\Http\Request), Object(Closure))
#22 /customers/c/e/1/jens/httpd.private/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(171): Laravel\Nova\Http\Middleware\Authenticate->handle(Object(Illuminate\Http\Request), Object(Closure))
#23 /customers/c/e/1/jens/httpd.private/vendor/laravel/framework/src/Illuminate/Routing/Middleware/SubstituteBindings.php(41): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(Object(Illuminate\Http\Request))
#24 /customers/c/e/1/jens/httpd.private/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(171): Illuminate\Routing\Middleware\SubstituteBindings->handle(Object(Illuminate\Http\Request), Object(Closure))
#25 /customers/c/e/1/jens/httpd.private/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php(76): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(Object(Illuminate\Http\Request))
#26 /customers/c/e/1/jens/httpd.private/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(171): Illuminate\Foundation\Http\Middleware\VerifyCsrfToken->handle(Object(Illuminate\Http\Request), Object(Closure))
#27 /customers/c/e/1/jens/httpd.private/vendor/laravel/framework/src/Illuminate/View/Middleware/ShareErrorsFromSession.php(49): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(Object(Illuminate\Http\Request))
#28 /customers/c/e/1/jens/httpd.private/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(171): Illuminate\View\Middleware\ShareErrorsFromSession->handle(Object(Illuminate\Http\Request), Object(Closure))
#29 /customers/c/e/1/jens/httpd.private/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(56): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(Object(Illuminate\Http\Request))
#30 /customers/c/e/1/jens/httpd.private/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(171): Illuminate\Session\Middleware\StartSession->handle(Object(Illuminate\Http\Request), Object(Closure))
#31 /customers/c/e/1/jens/httpd.private/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.php(37): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(Object(Illuminate\Http\Request))
#32 /customers/c/e/1/jens/httpd.private/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(171): Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse->handle(Object(Illuminate\Http\Request), Object(Closure))
#33 /customers/c/e/1/jens/httpd.private/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php(66): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(Object(Illuminate\Http\Request))
#34 /customers/c/e/1/jens/httpd.private/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(171): Illuminate\Cookie\Middleware\EncryptCookies->handle(Object(Illuminate\Http\Request), Object(Closure))
#35 /customers/c/e/1/jens/httpd.private/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(105): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(Object(Illuminate\Http\Request))
#36 /customers/c/e/1/jens/httpd.private/vendor/laravel/framework/src/Illuminate/Routing/Router.php(683): Illuminate\Pipeline\Pipeline->then(Object(Closure))
#37 /customers/c/e/1/jens/httpd.private/vendor/laravel/framework/src/Illuminate/Routing/Router.php(658): Illuminate\Routing\Router->runRouteWithinStack(Object(Illuminate\Routing\Route), Object(Illuminate\Http\Request))
#38 /customers/c/e/1/jens/httpd.private/vendor/laravel/framework/src/Illuminate/Routing/Router.php(624): Illuminate\Routing\Router->runRoute(Object(Illuminate\Http\Request), Object(Illuminate\Routing\Route))
#39 /customers/c/e/1/jens/httpd.private/vendor/laravel/framework/src/Illuminate/Routing/Router.php(613): Illuminate\Routing\Router->dispatchToRoute(Object(Illuminate\Http\Request))
#40 /customers/c/e/1/jens/httpd.private/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(170): Illuminate\Routing\Router->dispatch(Object(Illuminate\Http\Request))
#41 /customers/c/e/1/jens/httpd.private/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(130): Illuminate\Foundation\Http\Kernel->Illuminate\Foundation\Http{closure}(Object(Illuminate\Http\Request))
#42 /customers/c/e/1/jens/httpd.private/nova/src/Http/Middleware/ServeNova.php(26): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(Object(Illuminate\Http\Request))
#43 /customers/c/e/1/jens/httpd.private/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(171): Laravel\Nova\Http\Middleware\ServeNova->handle(Object(Illuminate\Http\Request), Object(Closure))
#44 /customers/c/e/1/jens/httpd.private/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(Object(Illuminate\Http\Request))
#45 /customers/c/e/1/jens/httpd.private/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(171): Illuminate\Foundation\Http\Middleware\TransformsRequest->handle(Object(Illuminate\Http\Request), Object(Closure))
#46 /customers/c/e/1/jens/httpd.private/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(Object(Illuminate\Http\Request))
#47 /customers/c/e/1/jens/httpd.private/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(171): Illuminate\Foundation\Http\Middleware\TransformsRequest->handle(Object(Illuminate\Http\Request), Object(Closure))
#48 /customers/c/e/1/jens/httpd.private/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ValidatePostSize.php(27): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(Object(Illuminate\Http\Request))
#49 /customers/c/e/1/jens/httpd.private/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(171): Illuminate\Foundation\Http\Middleware\ValidatePostSize->handle(Object(Illuminate\Http\Request), Object(Closure))
#50 /customers/c/e/1/jens/httpd.private/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/CheckForMaintenanceMode.php(63): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(Object(Illuminate\Http\Request))
#51 /customers/c/e/1/jens/httpd.private/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(171): Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode->handle(Object(Illuminate\Http\Request), Object(Closure))
#52 /customers/c/e/1/jens/httpd.private/vendor/fideloper/proxy/src/TrustProxies.php(57): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(Object(Illuminate\Http\Request))
#53 /customers/c/e/1/jens/httpd.private/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(171): Fideloper\Proxy\TrustProxies->handle(Object(Illuminate\Http\Request), Object(Closure))
#54 /customers/c/e/1/jens/httpd.private/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(105): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(Object(Illuminate\Http\Request))
#55 /customers/c/e/1/jens/httpd.private/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(145): Illuminate\Pipeline\Pipeline->then(Object(Closure))
#56 /customers/c/e/1/jens/httpd.private/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(110): Illuminate\Foundation\Http\Kernel->sendRequestThroughRouter(Object(Illuminate\Http\Request))
#57 /customers/c/e/1/jens/httpd.www/index.php(55): Illuminate\Foundation\Http\Kernel->handle(Object(Illuminate\Http\Request))
#58 {main}

Thanks!

Custom third party plugins

Is it possible to include custom third party Froala plugins? So this means not only embedly etc.

Sadly, I can't find anything for this in the documentation.

Froala key

Hi,
I purchased a license key, how activate it?

I put in config/nova/froala-field.php and doesn't work.

Field content isn't updated when changing in code view

Steps to reproduce:

  1. Go to resource which uses nova-froala-field
  2. Click Create new
  3. Write content into Froala editor
  4. Click save
  5. Click edit on content that was just created
  6. Go to Froala editor, click Code view
  7. Change content (example: add <p>test </p>)
  8. Click save

I would expect content to be changed, but it isn't. It remains the same, as it was on initial load (when clicked on edit, step 5). Not sure if this is intended behavior or it's a bug.

Laravel version: 5.8.16
Nova version: 2.0.3
Nova Froala field version: 2.1.0

Remove Powered by Froala

I have purchased the Froala License and activated it. However, I fail to remove the "Powered by Froala" attribution even I set :
'attribution' => true in the config file.

'filemtime(): stat failed' after nova update

Nova version: 2.8.0
Laravel version: 6.6.2
Nova froala field version: 3.2.1

Efter updating nova to 2.8, I'm getting the following error in nova:

filemtime(): stat failed for https://cdn.jsdelivr.net/npm/[email protected]/dist/tui-image-editor.css

Seems to happen when filemtime is ran on the remote files loaded in the FroalaFieldServiceProvider.php (line 21)

Nova::style('tui-editor', 'https://cdn.jsdelivr.net/npm/[email protected]/dist/tui-image-editor.css');
Nova::style('tui-color-picker', 'https://uicdn.toast.com/tui-color-picker/latest/tui-color-picker.css');

Declaration of showOnIndex() has changed

Error: Declaration of Froala\NovaFroalaField\Froala::showOnIndex() should be compatible with Laravel\Nova\Fields\FieldElement::showOnIndex($callback = true)

In Nova 2.1 (latest release).

Fix in Froala.php:

    /**
     * Specify that the element should be hidden from the index view.
     *
     * @param  \Closure|bool  $callback
     * @return $this
     */
    public function showOnIndex($callback = true)
    {
        $this->showOnIndex = $callback;

        return $this;
    }

Froala fields not displaying on index

Hi

I have the following code

public function fields(Request $request)
    {
        return [
            ID::make()->sortable(),
            Froala::make('Question')->withFiles('public')->sortable(),
            Froala::make('Answer')->withFiles('public')
        ];
    }

Which works fine when adding or editing a resource, but when i go to the index view of the resource i only get the ID and not the Question/Answer text displayed in the table

If i switch from Froala to a standard Text::make it then works and displays on the resource group index

Anyone have any ideas?

screenshot 2018-11-14 at 17 29 40
screenshot 2018-11-14 at 17 29 35

Issue with Manage Images

Hi, awesome plugin.

The issue I am having is when when trying to insert an image via the browser button, I expect to see a list of images but I see an empty modal window.

Looking into the request in chromes network panel, I can see I get a 404 error when a request is made to "/nova-vendor/froala-field/image-manager?resource=articles&field=content"

Screenshot 2019-05-06 at 17 18 46

vendor:publish not working

Non of the vendor:publish commands (copy/pasted from readme) works.
All of them (config, migration, fonts) says Publishing complete, but no new file is added.
I'm on a Windows PC, so I don't think if it's related to dir permissions, as publishing the assets of other packages just works.

All classes removed on save

Hi,

all classes are removed on save.

I extended the options to this:

    'options' => [
        // 'key' => env('FROALA_KEY'),
        'useClasses' => true,
        'htmlAllowedAttrs' => ['title','class', 'href', 'alt', 'src', 'style'],
        'htmlAllowedTags' => ['.*'],
        'htmlRemoveTags' => [''],
        'toolbarButtons' => [
            'bold',
            'italic',
            'underline',
            '|',
            'formatOL',
            'formatUL',
            '|',
            'insertImage',
            'insertFile',
            'insertLink',
            'insertVideo',
            '|',
            'html',
        ],
    ],

But this doesn't help.

Any suggestions how I can disable this?

Error when updating to Nova 2.7 - Trix was updated.

When trying to upgrade to Nova 2.7 I got some errors on the Froala Field, related to the parameters of withFiles.

Since the froala field is extending the \vendor\laravel\nova\src\Fields\Trix.php field, you should be aware in the the most recent versions of Nova( tested with 2.7), the withFiles method has a $path parameter.

Trix.php - withFiles function on 2.7

public function withFiles($disk = null, $path = '/')
    {
        $this->withFiles = true;

        $this->disk($disk)->path($path);

        $this->attach(new StorePendingAttachment($this))
             ->detach(new DetachAttachment($this))
             ->delete(new DeleteAttachments($this))
             ->discard(new DiscardPendingAttachments($this))
             ->prunable();

        return $this;
    }

Trix.php - withFiles function on 2.5

    public function withFiles($disk = null)
    {
        $this->withFiles = true;

        $this->disk($disk);

        $this->attach(new StorePendingAttachment($this))
             ->detach(new DetachAttachment($this))
             ->delete(new DeleteAttachments($this))
             ->discard(new DiscardPendingAttachments($this))
             ->prunable();

        return $this;
    }

Adding the parameter to the Froala.php 's withFiles method seems to work just fine locally.

For people that hit that issue, revert to a previous version of Nova until this is fixed.

Pulling through HTML tags onto page

I've installed this to use on my page content management section within Laravel Nova.

In nova the actual field appear to work fine, but when I pull the inputted content through to the front end of my site it pulls through the html tags with it (e.g p tags, li tags, ul tags, etc).

Am I missing something?
Thanks

Gallery Support question

Hi. This package looks great. I plan to buy it but I need to understand one think before.

About the upload capability, this editor support any kind of gallery? I mean, if I create a "post", and upload a image, if I need the same image in another "post", will I have to upload again the same image (having duplicated file in storage)? Or will I be able to select any of previously uploaded image?
In other words: The editor will be able to pick an already uploaded image?

I'm using https://github.com/ebess/advanced-nova-media-library the use the amazing https://github.com/spatie/laravel-medialibrary to manage my library package. Is it compatible? If not, I need compatibility with some kind of Gallery, in My case the end user MUST be able to reuse an uploaded image.

Events firing when editor loads

Hello,

Following the instructions, I have created a .js file containing my event handlers:

window.froala = {
    events: {
        'image.inserted': ($img, response) => {
            console.log('inserted');
        }
    }
};

And then loaded this file in NovaServiceProvider::boot method:

Nova::serving(function (\Laravel\Nova\Events\ServingNova $event) {
   Nova::script('froala-event-handlers', public_path('js/froala-event-handlers.js'));
});

So far so good, when an image is inserted in the editor, the event is fired.
However, the event is also fired when the page firstly loads, without even giving focus to the editor. Is this normal behaviour?

How to change language?

On config\nova\froala-field.php I tried:

    'options' => [
        'toolbarButtons' => [
            'bold',
            'italic',
            'underline',
            '|',
            'formatOL',
            'formatUL',
            '|',
            'insertImage',
            'insertFile',
            'insertLink',
            'insertVideo',
            '|',
            'html',
        ],
        'language' => 'pt_br',
    ],

and

    'options' => [
        'toolbarButtons' => [
            'bold',
            'italic',
            'underline',
            '|',
            'formatOL',
            'formatUL',
            '|',
            'insertImage',
            'insertFile',
            'insertLink',
            'insertVideo',
            '|',
            'html',
        ],
    ],
    'language' => 'pt_br',

, nothing happened.

Btw, is it possible to translate the Show Content and Hide Content?

Your requirements could not be resolved to an installable set of packages.

When I try froala/nova-froala-field I get the following error, can't understand what I am doing wrong.

 - Installation request for froala/nova-froala-field ^2.0 -> satisfiable by froala/nova-froala-field[2.0.0].
    - froala/nova-froala-field 2.0.0 requires laravel/nova ^2.0 -> no matching package found.

Composer.json

{
    "name": "laravel/laravel",
    "description": "The Laravel Framework.",
    "keywords": ["framework", "laravel"],
    "license": "MIT",
    "type": "project",
    "require": {
        "php": ">=7.0",
        "dmitrybubyakin/nova-medialibrary-field": "^1.1",
        "epartment/nova-dependency-container": "^1.1",
        "fideloper/proxy": "^4.0",
        "freshwork/chilean-bundle": "^2.0",
        "guzzlehttp/guzzle": "^6.3",
        "laravel/framework": "5.8.*",
        "laravel/nova": "*",
        "laravel/passport": "^7.0",
        "laravel/tinker": "~1.0",
        "maatwebsite/excel": "^2.1",
        "mpociot/laravel-apidoc-generator": "^2.0",
        "orlyapps/nova-belongsto-depend": "^0.0.8",
        "spatie/laravel-medialibrary": "^7.0.0",
        "spatie/laravel-permission": "^2.6",
        "webpatser/laravel-uuid": "^3.0"
    },
    "require-dev": {
        "doctrine/dbal": "~2.3",
        "filp/whoops": "~2.0",
        "fzaninotto/faker": "~1.4",
        "infyomlabs/adminlte-templates": "5.8.x-dev",
        "infyomlabs/laravel-generator": "5.8.x-dev",
        "laravelcollective/html": "^5.5.0",
        "mockery/mockery": "^1.1",
        "phpunit/phpunit": "~6.0"
    },
    "repositories": [
        {
            "type": "path",
            "url": "./nova"
        }
    ],
    "autoload": {
        "classmap": [
            "database"
        ],
        "psr-4": {
            "App\\": "app/"
        },
        "files": [
            "app/helpers.php"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "Tests\\": "tests/"
        }
    },
    "scripts": {
        "post-autoload-dump": [
            "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
            "@php artisan package:discover --ansi"
        ],
        "post-root-package-install": [
            "@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
        ],
        "post-create-project-cmd": [
            "@php artisan key:generate --ansi"
        ]
    },
    "minimum-stability": "dev",
    "prefer-stable": true,
    "config": {
        "preferred-install": "dist",
        "sort-packages": true,
        "optimize-autoloader": true
    }
}

translatable compatibility

I've tried froala field with spatie/laravel-translatable but it seems that its not compatible.
The error im getting is "Unknown column translations_content_en in field list"
Any plans to support this package?

Froala field disappear while typing

Laravel: v5.8.33
Laravel Nova: v2.1.1
Nova Froala Field: v3.1.0
Chrome: v76.0.3809.132
Firefox: v68.0.2

I have integrated this into my project and it works most of the time.
But some times the field disappear while I'm typing, along with the content.
This happens randomly, but only when I'm typing on this field.
When this happens, I can see some Vue components being rendered onto the DOM.
I have verified this issue in both Chrome and Firefox as well as on other PCs.

image
image

/dist/js/field.js duplicate code

/dist/js/field.js has gone from 712kb in this commit https://github.com/froala/nova-froala-field/blob/2c2fef1d0cfe27416776c988df4cdd301bae2068/dist/js/field.js to 2.66mb in the latest update to the file: https://github.com/froala/nova-froala-field/blob/a2126c44721ef67c8156a7c53664241408234ae8/dist/js/field.js This results in the full 2.66mb file being published to the Nova scripts URL at /nova-api/scripts/nova-froala-field and loaded every time a user visits the Nova backend.

One of the problems is that the JS file contains two identical 1.33mb code blocks. To check this, visit the raw file here: https://raw.githubusercontent.com/froala/nova-froala-field/a2126c44721ef67c8156a7c53664241408234ae8/dist/js/field.js, copy any large code block, and do a find on it. You'll see it appear again halfway through the file. Or, download the file, open in a text editor, and turn off line wrapping. Lines 1 and 2 of the file are identical code blocks:

Dec-06-2019 10-52-20

It's possible there's other duplications as well. For example, this code block appears 4 times in the file, and should probably only appear once:

eplace(/\[FROALA\.EDITOR\.NOSCRIPT ([\d]*)\]/gi,function(t,n){return 0<=e.opts.htmlRemoveTags.indexOf("noscript")?"":c[parseInt(n,10)].replace(/&lt;/g,"<").replace(/&gt;/g,">")})).replace(/<img((?:[\w\W]*?)) data-fr-src="/g,'<img$1 src="')}(function(t,n,r){if(e.opts.fullPage){var o=e.html.extractDoctype(r),a=f(e.html.extractNodeAttrs(r,"html"));n=null===n?e.html.extractNode(r,"head")||"<title></title>":n;var i=f(e.html.extractNodeAttrs(r,"head")),s=f(e.html.extractNodeAttrs(r,"body"));return"".concat(o,"<html").concat(a,"><head").concat(i,">").concat(n,"</head><body").concat(s,">").concat(t,"</body></html>")}return t}(o,a,t))}function h(t){var n=e.doc.createElement("DIV");return n.innerText=t,n.textContent}function g(i){for(var s=e.node.contents(i),l=0;l<s.length;l++)s[l].nodeType!==Node.TEXT_NODE&&g(s[l]);!function(i){if("SPAN"===i.tagName&&0<=(i.getAttribute("class")||"").indexOf("fr-marker"))return!1;if("PRE"===i.tagName&&function(e){var t=e.innerHTML;0<=t.indexOf("\n")&&(e.innerHTML=t.replace(/\n/g,"<br>"))}(i),i.nodeType===Node.ELEMENT_NODE&&(i.getAttribute("data-fr-src")&&0!==i.getAttribute("data-fr-src").indexOf("blob:")&&i.setAttribute("data-fr-src",e.helpers.sanitizeURL(h(i.getAttribute("data-fr-src")))),i.getAttribute("href")&&i.setAttribute("href",e.helpers.sanitizeURL(h(i.getAttribute("href")))),i.getAttribute("src")&&i.setAttribute("src",e.helpers.sanitizeURL(h(i.getAttribute("src")))),0<=["TABLE","TBODY","TFOOT","TR"].indexOf(i.tagName)&&(i.innerHTML=i.innerHTML.trim())),!e.opts.pasteAllowLocalImages&&i.nodeType===Node.ELEMENT_NODE&&"IMG"===i.tagName&&i.getAttribute("data-fr-src")&&0===i.getAttribute("data-fr-src").indexOf("file://"))return i.parentNode.removeChild(i),!1;if(i.nodeType===Node.ELEMENT_NODE&&t.HTML5Map[i.tagName]&&""===e.node.attributes(i)){var s=t.HTML5Map[i.tagName],l="<".concat(s,">").concat(i.innerHTML,"</").concat(s,">");i.insertAdjacentHTML("beforebegin",l),(i=i.previousSibling).parentNode.removeChild(i.nextSibling)}if(e.opts.htmlAllowComments||i.nodeType!==Node.COMMENT_NODE)if(i.tagName&&i.tagName.match(r))i.parentNode.removeChild(i);else if(i.tagName&&!i.tagName.match(n))"svg"===i.tagName?i.parentNode.removeChild(i):e.browser.safari&&"path"===i.tagName&&i.parentNode&&"svg"===i.parentNode.tagName||(i.outerHTML=i.innerHTML);else{var c=i.attributes;if(c)for(var f=c.length-1;0<=f;f--){var p=c[f],u=p.nodeName.match(o),g=null;"style"===p.nodeName&&e.opts.htmlAllowedStyleProps.length&&(g=p.value.match(a)),u&&g?p.value=d(g.join(";")):u&&("style"!==p.nodeName||g)||i.removeAttribute(p.nodeName)}}else 0!==i.data.indexOf("[FROALA.EDITOR")&&i.parentNode.removeChild(i)}(i)}return{_init:function(){e.opts.fullPage&&i.merge(e.opts.htmlAllowedTags,["head","title","style","link","base","body","html","meta"])},html:function(t,s,l,c){void 0===s&&(s=[]),void 0===l&&(l=[]),void 0===c&&(c=!1);var d,f=i.merge([],e.opts.htmlAllowedTags);for(d=0;d<s.length;d++)0<=f.indexOf(s[d])&&f

Trimming /dist/js/field.js back down to a reasonable size by removing duplicate code would help speed up our Nova backend. Thanks!

Content saved in 'html' view are not persisting

We use this package for a laravel project. When editing content inside the froala editor, we oftentimes like to see it in code view to remove unwanted markup. It's unexpected behavior to have to exit code view in order to save the changes.

Attachments not working when Froala field is translatable

Hello,

I am using spatie/laravel-translatable to have my models translatable, and also spatie/nova-translatable to manage the translatable fields through Nova.

When using Froala field alone, like this:

Froala::make('Body')
    ->withFiles('images')
    ->showOnIndex()

everything works fine.

However, when I combine it with Translatable field:

Translatable::make([
    Froala::make('Body')
        ->withFiles('images')
        ->showOnIndex()
]),

attachments don't work anymore.

Dev tools inspector shows the following error:
POST http://site.local/nova-vendor/froala-field/pages/attachments/translations_body_en 404 (Not Found)
I guess that field here should be just "body", but due to translatable package it becomes "translations_body_en"?

Is it, by any chance, possible to fix the compatibility between the two packages?

Thanks in advance,
Ilias

Loading images using artisan serve

As mentioned in here: #18
There is an issue using getimagesize on local assets using url when running php artisan serve.

Just an idea. Check if the driver is local and if so use path instead

if (config('filesystems.disks')[$this->field->disk]['driver']) == 'local') {
        $path = $Storage->path($file);
    } else {
        $path = $Storage->url($file);
    }

    if (! app()->runningUnitTests() and ! @getimagesize($path)) {
        continue;
    }

Options with $ on field declaration

Hi,

I am trying to change the enter key behaviour on my Field in nova,
On the documentation it is stated that we should use:

'enter'=> '$.FroalaEditor.ENTER_DIV',

on the options of the field, which in my case doesn't work and messes up my inputs with tags.

What is the right way to use options like that?

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.