В данной статье я хочу рассказать про мой callback-виджет, который я решил разработать для поставленной задачи!
Суть задачи заключалась в следующем:
- 1. Разработать удобный для заказчика и клиента виджет средства связи
- 2. Оперативно и быстро написать его
- 3. С поддержкой Cross Domain requests
- 4. С быстрой установкой в одну строчку кода
- 5. Быстро настраиваемый
- 6. E-mail рассылка
Решение:
Перед тем как начать писать код, я продумал архитектуру и из самых простых инструментов для backend я использовал php, а front-end native js + angular без использования других jquery-подобных библиотек. Для того, чтобы виджет был уникальным, каждый виджет имеет свой универсальный ключ, по которому мы и будем получать все данные по виджету.
Я не хочу писать огромные куски кода логики, которые каждый разработчик в силах додумать, а хотел бы отметить те моменты, на которые я потратил больше всего времени, хотя и в веб-разработке уже не первый год.
Приступим к разбору узких мест!
Как выглядит код для вставки на сайт (index.html):
<script type="text/javascript" charset="utf-8" src="http://domain.ru/widget-get?key=a3234cc36aa23123456a59c281e51e50"></script>
(key — это сгенерированный md5 ключ, по которому я получаю всю информацию по виджету, а не по ID это очень важно, а рекомендуемое место вставки это до закрываеющего тега </body>)
Как выглядит backend код написанный на php, который отдаёт нам необходимые элементы для вставки:
Обработчик:
<?php class ControllerWidgetGet extends Controller { public function index(){ if (isset($this->request->get['key'])){ $data['key'] = $this->db->escape($this->request->get['key']); if ($row = $this->checkValidKey($data['key'])){ $data['row'] = $row; $this->response->setOutput($this->load->view('/widget/get.tpl', $data)); }else{ echo 'alert("Проверьте правильность вашего ключа");'; } } } public function checkValidKey($key){ $query_key = $service = $this->db->query("SELECT * FROM `" . DB_PREFIX . "widget` WHERE `key_get` = '" . $key . "'"); return $query_key->row; } }
Шаблон (get.tpl):
document.write('<link href="http://domain.ru/widget/production/tracker.css" rel="stylesheet"/><script src="http://yastatic.net/angularjs/1.3.16/angular.min.js"></script><script src="http://domain.ru/widget/production/tracker.js"></script><div ng-app="widgetApp"><widget scolor="<?=$row['s_color'];?>" spoints="<?=$row['s_points'];?>" spmenu="<?=$row['s_p_menu'];?>" spwidget="<?=$row['s_p_widget'];?>" sworktime="<?=$row['s_work_time'];?>" key="<?=$key;?>"></widget></div>');
где:
<link href="http://domain.ru/widget/production/tracker.css" rel="stylesheet"/> - наши стили
<script src="http://yastatic.net/angularjs/1.3.16/angular.min.js"></script> - cdn используемая библиотека
<script src="http://domain.ru/widget/production/tracker.js"></script> - логика нашего приложения
<div ng-app="widgetApp"><widget scolor="<?=$row['s_color'];?>" spoints="<?=$row['s_points'];?>" spmenu="<?=$row['s_p_menu'];?>" spwidget="<?=$row['s_p_widget'];?>" sworktime="<?=$row['s_work_time'];?>" key="<?=$key;?>"></widget></div> - инициализация нашего angular приложения, с передаваемыми параметрами в Виджет
Читая различные маны(stackoverflow и др.) по вставке элементов в html с использованием js, железно работает только document.write. Но на этом вся история ещё не останавливается, на данный момент у нас только получилось загрузить к нам на сайт *.css, *.js, но нам также для вывода нашего виджета потребуется много html разметки, и тут стали приходить различные варианты!
Директива Angular поддерживает следующий template:
#1
.directive('myDialog', function() { return { templateUrl: 'http://domain.ru/my-dialog.html' };
#2
.directive('myDialog', function() { return { template: '<div ng-controller="MyController"><h1>{{textHello}}</h1></div>' };
Комментарий к #1:
Не кроссдоменное решение, он забирает методом GET .html разметку и выпадают ошибки вида:
“No ‘Access-Control-Allow-Origin’ header is present on the requested resource”
посмотрим что скажет на это stackoverflow
Комментарий к #2:
Здесь понятно, что внутри нашего /tracker.js мы не прибегаем к загрузке html с другого источника, а у нас есть возможность вставить его просто в параметр template, супер! Но казалось бы как так? Разве мы не можем сделать кроссдоменный запрос типа JSONP и забрать HTML, подумали вы? НЕТ!
Смотрим сюда stackoverflow
Просто замечтательно!
Инструменты напоследок:
Для сжатия я использовал следующий конфигурационный файл gulp.js
var gulp = require('gulp'), minifyHTML = require('gulp-minify-html'), sass = require('gulp-sass'); autoprefixer = require('gulp-autoprefixer'), minifycss = require('gulp-minify-css'), rename = require('gulp-rename'), concat = require('gulp-concat'), uglify = require('gulp-uglify'); gulp.task('p-ht', function() { var opts = { conditionals: true, spare:true }; return gulp.src('src/html/index.html') .pipe(minifyHTML(opts)) .pipe(gulp.dest('dest/html/')) }); gulp.task('p-st', function() { //return gulp.src('src/styles/main.scss') //.pipe(sass({style: 'expanded'})) return gulp.src('src/styles/tracker.css') .pipe(autoprefixer('last 2 version')) .pipe(gulp.dest('dest/styles/')) //.pipe(rename({suffix: '.min'} )) .pipe(minifycss()) .pipe(gulp.dest('dest/styles/')) }); gulp.task('p-sc', function() { return gulp.src('src/scripts/*.js') .pipe(concat('tracker.js')) .pipe(gulp.dest('dest/scripts/')) //.pipe(rename({suffix: '.min'})) .pipe(uglify()) .pipe(gulp.dest('dest/scripts/')) }); gulp.task('watch', function() { gulp.watch('src/scripts/*.js', ['p-sc']) }); gulp.task('dev', ['p-st', 'p-sc', 'watch'], function () { }); gulp.task('build', ['p-st', 'p-sc', 'p-ht'], function () { });
Комментарий: при сжатии html символ одинарной кавычки экранируйте при использовании с ng-class={\’test-class\’: expression}, и следите за символами в регулярных выражениях, js-редактор обычно подсвечивает, подсвеченные символы экранируйте
Для копирования кода в буфер я использовал следующий код, расположенный на stackoverflow
Заключение:
Хотелось бы отметить для более точного понимания, данный код работает на любых сайтах, а не только на локальном! Запросы, которыми я обмениваюсь со своим сервером исключительно JSONP!
Всем удачи в разработке!
ссылка на оригинал статьи http://habrahabr.ru/post/264211/
Добавить комментарий