Kitaboo SDK components¶
TOC (Table of Contents)¶
Introduction¶
The Table of Contents (TOC) contains all the information about book pages and contents. This feature can be used to generate a Table of Contents for the project. The TOC can be used to navigate to a specific text, pages or information in a book through Index terms and Bookmarks.
Implementation¶
Kitaboo SDK supports a default TOC view to show the different view as per tabs. User can customise TOC view in their own ways.
Basic view for TOC
Use the following code to add TOC to your reader :
Basic integration for TOC tab // toc view implementation started var container = document.getElementById('tocholder'); var defaultOpts = { container: container, data: render.book.bookdata.toc } /** * option for toc * container: container which holds the toc view * data: toc data */ toc = new TOCManager(defaultOpts); Basic integration for Bookmark tab if (bookmarkobj.bookmarkManager.listofbookmarks.length == 0) { $("#bookmarkholder").html("<span class='not-available'>No Bookmarks Available</span>"); } else { var bookmarkContainer = document.getElementById('bookmarkchild'); var bookmarkData = []; for (var i = 0; i < globaledata.length; i++) { if (globaledata[i].type == 4 && globaledata[i].status != 'DELETE') { bookmarkData.push(globaledata[i]); } } bookmarkobj.createBookmarkView(bookmarkData, bookmarkContainer); } Basic integration for Resource tab /** * option for resource * container: container which holds the resource view */ // resources with their id on server. Map the server id of resource to it's type var resourcesConvertor = { 'documents' : 1, 'video' : 2, 'audio' : 3, 'image' : 4, 'web links' : 5, 'htmlwrap' : 6, 'activity' : 7, 'toc' : 8, 'pagestatus' : 9, 'kaltura_video' : 10, 'external_web_link': 11, 'textinput' : 12, 'dropdown' : 13, 'external_image' : 14, 'external_audio' : 15, 'external_video' : 16, 'external_documents': 17, 'kitaboowidget' : 18, 'external_htmlwrap': 19, 'youtube_video' : 21, 'survey' : 22, 'slideshow' : 23, 'glossary' : 24, 'imagezoom' : 25, 'jumptobook' : 26, 'external_imagezoom': 27, 'standalone_instruction' : 28, 'teacher_exclusive': 29, '1' : 1, '2' : 2, '3' : 3, '4' : 4, '5' : 5, '6' : 6, '7' : 7, '8' : 8, '9' : 9 } // resource config var resourceParams = { container: resourceContainer }; // create resource object resourceManager = new ResourceManager(resourceParams); // create filter resources collections which we can show in tab var resourcesCollection = []; book.resources.forEach(function(returnableObjects){ var resource = returnableObjects.subitems.filter(function (item) { // hide toc, page status, weblink, gotopage, glossary, jumptobook, fib, and dropdown resources return ([5, 8, 9, 12, 13, 24, 26].indexOf(Number(resourcesConvertor[item.typeId.toLowerCase()])) < 0 || item.displayUnderTOR); }); resourcesCollection.push({id: returnableObjects.id, title: returnableObjects.title, subitems: resource}); }); //assign collection to create view for resources in Resource tab resourceManager.createResourceView(resourcesCollection);
Customization¶
Kitaboo SDK supports a TOC component to show the table of contents of a book in the reader. You can either customize the entire TOC component or make simple changes to the TOC that comes with Kitaboo reader by just changing the font and CSS. If you want to replace the entire TOCView with your own, then you can just use the data and create your own view.
1. Basic customization
Using CSS you can customize the following:
1.1. Theme
Allows you to set the theme color using id #tocchild and its child components
1.2. Add or Remove tabs
This will allow you to remove tabs in TOC view or change label etc.
var toc-tab-btn= document.getElementsByClassName('bookmark-tab-btn'); var bookmarkTab = document.getElementsByClassName('bookmark-tab-btn'); var resourceTab = document.getElementsByClassName('resources-tab-btn'); resourceTab[0].style.display = "none";
2. Advanced customization
Creating your own custom Toc View and utilizing the same on Reader.
Here, we are going to display TOC data in a custom list (using repeat). On click of TOC menu item, define your custom listview and render same using data in tocData object.
tocdata = book.bookdata.toc
On click of Bookmark tab menu item, define your custom listview and render the same using data in bookmarkData, and we need to decode metadata of bookmark object so that it becomes readable content and can display it in view.
bookmarkData = []; $scope.bookmarkData = globaledata, { 'type': 4, 'status': '!DELETE' }; if (bookmarkData.length > 0) { for(var count = 0; count <bookmarkData.length ;count ++){ if (bookmarkData[count ].metadata !== "" && bookmarkData[count ].metadata.createdOn === undefined) { bookmarkData[count ].metadata = JSON.parse(decodeURIComponent(bookmarkData[count ].metadata)); } }); }
On click of Resource tab menu item, define your custom listview and render the same using data in resourcesData, and we can use the data to display the icons and labels and resourcesLength can be used to display the no data message if no resources are available.
/** * option for resource * container: container which holds the resource view */ // resources with their id on server. Map the server id of resource to it’s type var resourcesConvertor = { 'documents': 1, 'video': 2, 'audio': 3, 'image': 4, 'web links': 5, 'htmlwrap': 6, 'activity': 7, //Porto is 6 'toc': 8, 'pagestatus': 9, 'kaltura_video': 10, // Porto is 16 'external_web_link': 11, 'textinput': 12, 'dropdown': 13, 'external_image': 14, 'external_audio': 15, 'external_video': 16, 'external_documents': 17, 'kitaboowidget': 18, 'external_htmlwrap': 19, 'youtube_video': 21, 'survey': 22, 'slideshow': 23, 'glossary': 24, 'imagezoom': 25, 'jumptobook': 26, 'external_imagezoom': 27, 'standalone_instruction': 28, 'teacher_exclusive': 29, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9 }; // resource config var resourceParams = { container: resourceContainer, }; // resourceManager = new ResourceManager(resourceParams); // create filter resources collections which we can show in tab var resourcesCollection = []; book.resources.forEach(function (returnableObjects) { var resource = returnableObjects.subitems.filter(function (item) { // hide toc, page status, weblink, gotopage, glossary, jumptobook, fib, and dropdown resources console.log([5, 8, 9, 12, 13, 24, 26].indexOf(Number(resourcesConvertor[item.typeId.toLowerCase()])), '[5, 8, 9, 12, 13, 24, 26].indexOf(Number(resourcesConvertor[item.typeId.toLowerCase()]))', item); return ([5, 8, 9, 12, 13, 24, 26].indexOf(Number(resourcesConvertor[item.typeId.toLowerCase()])) < 0 && item.displayUnderTOR); }); resourcesCollection.push({ id: returnableObjects.id, title: returnableObjects.title, subitems: resource }); }); if (resourcesCollection.length > 0) { resourcesData = resourcesCollection; resourcesLength = true; } else { resourcesLength = false; } }
Now, you can perform required action on Toc item click.
- Toc Item click event callback
As we are using sdk toc data so we can pass the complete tocObject to navigateToPage method and it will redirect to desired page.
render.navigateToPage(tocObject);
And any item navigation for bookmark and resource just need to pass folioID
And we are displaying bookmark and resources in custom view so the object is not same as SDK so we can pass the folioID and startWordIndex and EndWordIndex to navigateToPage method and it will redirect to the desired page.
- Bookmark and resource navigation
render.navigateToPage({ "href": '#bookmark_' + (obj.folioID) + ':' + obj.metadata.StartWordIndex + "_" + obj.metadata.EndWordIndex, "spinePos": parseInt(obj.folioID) });
Highlight¶
Introduction¶
Use the Highlight tool to select text to highlight it with different colors or add a contextual note. You can also highlight data based on an already-performed activity.
Implementation¶
Kitaboo SDK provides the flexibility to customize the highlight color, which means the user can add multiple highlight color icons,contextual note icons, search and delete icons on the highlight panel.
To customize the highlight tool, you need to first create and initialize the CSS for the toolbar using the following code :
1. Initialization
Highlight component with config and pass desired style in config defaultHighlighCSS object
Note
We can only customize the UI of delete highlight icon as it is coming from sdk. It only appears if you click on already highlighlighted area. We get that object in HIGHLIGHT_CLICKED event only
/** * Highlight and Note contextual menu configuration object * @param {object} config * @param {string} [config.textSelectionCSS] : */ var config = { textSelectionCSS: "color:white; background:red", defaultHighlighCSS:"border-radius:23px;opacity:1.0;padding-left:5px;padding-right: 5px;background-color: rgba(0, 0, 0, 0.6) !important;display:none;height:50px;", stickynotetext: "¸", // icon for sticky note contextualnoteicon: 'V', // icon for context note isKitabooHighlightsupport: (book.bookdata.metadata.layout === "pre-paginated")// kitaboo native books highlight support } // create highlight class object var highlight = new kitaboohighlight(config); highlight.setScrollMode(true); //if reflowable default have scroll mode on
Once you have created your custom toolbar, follow the below events to capture user actions and update the view
2. Create Highlight Button
To add the Highlight colors, either you can add object of highlight one by one or you can add them dynamically using iterative methods
for example: HighlightColor is an array of colors for Highlight. for (var count= 0; count < HighlightColor.length ; count++){ var highlightId = 'highlight+_'+ count; // any id can be provided var item = { icon: '"', id: highlightId , css: "color:" + HighlightColor[count ] }; highlight.addItem(item); });
- Add button in Highlight Panel
highlight.addItem(item);
Highlight Listeners¶
Highlight Colors are already added in context menu. Now the item click event handles its functionality and we can also add any additional functionality to customize the behaviour.
highlight.on(highlight.HIGHLIGHT_MENU_ITEM_CLICKED, function(highlightobject) { if (highlightobject.item.id == ' 'highlight+_'+ count;') { // check all the id's used for highlight and handle here var drawcss = { backgroundColor: highlightobject.item.style.color, color: "", element: "span" } highlightobject.highlight.important = "N"; if (highlightobject.highlight.status == 'update') { highlight.editHighlight(highlightobject.highlight, drawcss); for (var i = 0; i < globaledata.length; i++) { if (globaledata[i].id == highlightobject.highlight.id) { /*update highlight object in globaledata*/ globaledata[i].status = 'update'; globaledata[i].important = "N"; break; } } } else if (highlightobject.highlight.id == 0 && MODE == 'EDIT') { var jsondata = JSON.parse(decodeURIComponent(highlightobject.highlight.metadata)); for (var i = 0; i < globaledata.length; i++) { var object = JSON.parse(decodeURIComponent(globaledata[i].metadata)); if (jsondata.StartWordIndex == object.StartWordIndex && jsondata.EndWordIndex == object.EndWordIndex) { globaledata.splice(i, 1); highlight.addHighlight(document.activeElement.contentDocument, highlightobject.highlight, drawcss); } } highlight.hide(); } else { highlight.addHighlight(document.activeElement.contentDocument, highlightobject.highlight, drawcss); } } else { highlight.addHighlight(document.activeElement.contentDocument, highlightobject.highlight, drawcss); } //globaledata.push(highlightobject.highlight); } else if (highlightobject.item.id == '102') { highlight.hide(); highlightobject.highlight.type = 2; highlightnote.showInEditMode(highlightobject.highlight); } highlightEnable = false; // highlight button state $('.highlightBttn').toggleClass('active', highlightEnable);// toggle highlight button class render.enableHighlight(highlightEnable); // enable highlight button render.showAllMarkups(); // show all markups }); // add the create object in highlight object. when user selects text on document. // Popup will contain the above custom object(item1, item2) Examples: highlight.addItem(item1); highlight.addItem(item2); highlight.addItem(item3); // add sticky note in DOM render.on("sticky:add", function(object) { console.log(object) highlightnote.showInEditMode(object); }); // draw custom highlight highlight.on(highlight.HIGHLIGHT_CLICKED, function(assetobject) { highlight.showInEditMode(assetobject); $("#800").css({ // Css for Highlight delete icon "color": "#7aa2bc", "font-size": "22px" }); }); // remove the highlight or note for custom items
You can call Save on user interaction
highlight.on(highlight.HIGHLIGHT_REMOVE, function(highlightobject) { }); // update the drawn higlight or note or and custom item with new values highlight.on(highlight.HIGHLIGHT_UPDATE, function(highlightobject) { console.log('update', highlightobject); }); // event dispatched add highlight object to collection highlight.on(highlight.HIGHLIGHT_ADD, function(highlightobject) { }); /** * event dispatched on custom item clicked in context menu * custom item create by user and information. * using which he/she can manipulate the selection on DOM */
Customization¶
-
Set background of highlight selection, set selection area shape, set items text color, set stroke width in defaultHighlighCSS and passing it in config while intialization defaultHighlighCSS: "border-radius: 23px;opacity: 1.0;padding-left: 5px;padding-right: 5px;background-color: rgba(0, 0, 0, 0.6) !important;display:none;height:50px;",
-
We can customize the delete highlight icon as well, but as it is predefined and only appears if you click on already highlighlighted area, we get that object in HIGHLIGHT_CLICKED event only.
$("#800").css({ // Css for Highlight delete icon "color": "#7aa2bc",** "font-size": "22px"** });**
Draw Highlight on the Document
To get the selected text of Highlighted Feature
// once DOM selection complete. show popup for editing render.on("highlight:section", function(textobject, page) { highlightrange = textobject; highlight.show(textobject, page); });
Search¶
Introduction¶
You can search for specific data from the book content.
Implementation¶
Use the following code to search for text in a book:
/** * @property: (book.bookdata.metadata.layout === "pre-paginated") * checked if book is fixed layout book, search.json logic will work * else reflow loading all DOM pages and creating page collection for search * for DOM implementation call function as below * searchObj.parseSearchFromPackage(bookObj) * above function requires book object */ var config = { kitabooSeachSupport: true, // default check search.json groupSearchResultForPage: (book.bookdata.metadata.layout !== "pre-paginated") // group search result in reflow book } search = new KitabooSearch(renderer.book, config); search.on("search:fail",function(response){ console.log(response, 'search file failed to load'); var search_container = document.getElementsByClassName('search-container'); if(search_container != null){ // search_container[0].style.display = 'none'; } }); search.loadSearchData(); search.on("search:result", function(searchresult) { if (searchresult.length == 0) { render.clearAndHighlightSearch(); } search.setData(searchresult); var $filterdata = searchresult; if ($filterdata.length === 0) { $('.search-panel').css('height', '90px'); } else { var dynamicHeight = ($filterdata.length * 100) > ($(window).height() - 170) ? ($(window).height() - 170) : ($filterdata.length * 100); $('.search-panel').css('height', (dynamicHeight + 60 /*padding*/ ) + 'px'); } search.show(); }); search.on("search:ItemClick", function(searchOject) { render.search(searchOject); search.hide(); });
Customization¶
Kitaboo SDK supports a Search component to show the result of the search made for the content of the book. You can either customize the entire Search component or make simple changes to the Search that comes with Kitaboo reader by just changing the font and CSS. If you want to replace the entire Search with your own, then you can just use the data and create your own view.
1. Basic customization
Using CSS you can customize the following:
Theme
Allows you to set the theme color using id #searchlist and its child components.
2. Advanced customization
Creating your own custom Search View and utilizing the same on Reader.
Here, we are going to display Search data in a custom list (using repeat).
- On click of Search button, define your custom listview and render same using data in searchresult object.
search.on("search:result", function(searchresult) { if (searchresult.length == 0) { render.clearAndHighlightSearch(); }
- On click of Search Item, define your custom action and use the highlighting of searched item of reader together using below mentioned line.
render.search(searchOject);
Example Project¶
The Search Example project is a sample code reference of SDK Integration with fully functioning Search Component. Click here to Download the project.
Note¶
Introduction¶
Note is a piece of information that users can put on the page. Kitaboo Sdk facilitates Note feature, which can be used for saving page data or user comments on page. The Note feature allows readers to create and share notes. You can associate a note to a word, phrase, sentence, paragraph or multiple paragraphs.
Contextual note: Note creation is done using selected text where position of note depends upon selected text position.
Sticky note: Note creation is done by clicking anywhere in Page-area, where position of note depends on selected page area (X,Y) points.
Implementation¶
Contextual Notes and Sticky Notes are the same here, we are only differentiating using highlighted text. If selected text is shown in note then it's contextual note otherwise sticky note.
Use the following code to add notes to your reader :
/* * create a note configuration object * @param {object} noteconfig: {locale: {buttons: {}, messages: {}}, container: document.body} */ var noteconfig = { locale: { buttons: { cancel: 'Cancel', post: 'Post', share: 'Share', done: 'Done', close: 'Close' }, messages: { shareInNotePopup: 'Share this note with', notePlaceHolder: 'Enter your note', highlightImportant: 'Click to make this note important', highlightNormal: 'Click to make this note normal' } }, isDefaultNotesPopup: true } /* * create a note object * @param {object} noteconfig: {textSelectionCSS: '', defaultHighlighCSS: ''} */ var highlightnote = new KitabooNotes(noteconfig); noteHighlightData = globaledata.filter(function(data){ return ((data.type === 1 || data.type === 2) && data.status != 'DELETE'); }); highlightnote.setUserVO(syncManager.syncAdapter.userVO); // assign current user highlightnote.setNoteShareData(noteHighlightData); // note data from server highlightnote.setNoteData(shareSettingData); // shared setting highlightnote.setShareData(shareData); // shared data
Events :
// save highlight or notes data highlightnote.on(highlightnote.SAVE_NOTES, function(highlightobject) { var drawcss = { backgroundColor: highlightobject.important == true ? "red" : "yellow", color: "", element: "span" } highlight.addHighlight(document.activeElement.contentDocument, highlightobject, drawcss); }); /* sticky note updated */ highlightnote.on('sticky:update', function(noteObject) { for (var i = 0; i < globaledata.length; i++) { if (globaledata[i].id == noteObject.id) { globaledata[i] = noteObject; console.log(globaledata[i]); break; } } }); // contextual note click highlightnote.on("note:stickyClick", function(highlightobject) { highlightnote.showInEditMode(highlightobject); }); // contextual note deleted highlightnote.on(highlightnote.NOTE_DELETED, function(id, highlightobject) { }); //share note data highlightnote.on("note:onDoneClick", function(ugcData, noteShareDataObject) { });
Customization¶
If you are using your custom popup, then you have to follow the below mentioned steps :
isDefaultNotesPopup : false // so default pop should not appear Open your popup in below mentioned events sticky:add "note:stickyClick 3) On Text change call highlightnote.onNotesTextChanges(event); 4) On Save call highlightnote.onPostClick(event); 5) On Delete call highlightnote.onDeleteClick(event);
Bookmark¶
Introduction¶
Kitaboo Sdk exposes a component which helps the user to create a list of favorite pages. List of Bookmark is available in Toc View in the Bookmark Tab.
A bookmark is a saved shortcut that directs you to a specific page in the book. It stores the title, text, and favicon of the corresponding page. Saving bookmarks allows you to easily access your favorite locations in the Book.
Implementation¶
Use the following code to add a bookmark to your reader :
// bookmark started var option = { defaultPopup: true, // if default popup is needed charlimit: 100, // character limit for title for bookmark bookmarkpostion: "right", // bookmark placement on right or left bookmarkselectcolor: '#43dbf2', // selection color bookmarkunselectcolor: '#a9a9a9', // default color container: document.body, // parent book: book, // book bookmarkIcon: 'q', // bookmark icon font code locale: { // locale label: { remainingChars: 'Chars: ', // label for max character }, buttons: { // buttons label add: 'Add', // add bookmark button label save: 'Save', // update bookmark button label delete: 'Delete', // delete bookmark button label }, messages: { } } } // create bookmark with above options var bookmarkobj = new Bookmark(option);
Events :
/** * event triggers when current active pages are visible * @return {object} event: contains chapter and document information * @return {object} event.chapter: current loading chapter object * @return {object} event.data: current loading document */ renderer.on("viewer:doc_loaded", function(event){ var chapter = event.chapter; bookmarkobj.setLabel(chapter.chapterName); bookmarkobj.addViewOnPage(chapter, event.data); var listofbookmark = getPagebookmarks(chapter); bookmarkobj.addBookmarkOnPageFromUGC(listofbookmark); }); /** * event triggers when current active pages are visible * @return {number} current active page number */ renderer.on("viewer:pagechange", function(event){ bookmarkobj.checkBookmark(event); bookmarkobj.hide(); });
Customization¶
- We can customize the bookmark icon by changing the bookmarkIcon in option.
bookmarkIcon: 'q', // bookmark icon font code
- We can change the locale to provide the custom messages.
locale: { // locale label: { remainingChars: 'Chars: ', // label for max character }, buttons: { // buttons label add: 'Add', // add bookmark button label save: 'Save', // update bookmark button label delete: 'Delete', // delete bookmark button label }, messages: { }
-
We allow you to set the theme color using class ".bookmark-popup" and its child components
-
We can use custom bookmark popup replacing default popup
defaultPopup: false, // if default popup is needed
MyData¶
Introduction¶
MyData is a feature supported by Kitaboo Sdk which helps to display the total number of Notes (Contextual and Sticky Note) and Highlights available for a book in a listview under "MyData". Here you will get information like: chapter name, page id, saved page data, data & time. It consists of shared[Notes/highlight] data between multiple users as well.
Implementation¶
Use the following code in your reader :
// MYData view implementation started eg., highlight, notes var myDataContainer = document.getElementById("mydatalist"); userdataObj = new MYData({ container: myDataContainer }); /** * MYData event handler * @param {string} [spinePos] : index in spineItem(refer book data) **/ userdataObj.on("mydata:itemClick", function(mydataobject) { // hide the MYData container togglePopUpContainer('mydata-panel'); render.navigateToPage(mydataobject); //highlightnote.shareNoteShowInEditMode(mydataobject); }); userdataObj.on("data:shareReceive", function(shareDataObject) { //togglePopUpContainer('mydata-panel'); // needed if we want to close popup $('#myDataConfirmation').show(); /*object passing to saveHighlightSetting service*/ syncManager.syncAdapter.saveHighlightSetting(usertoken, bookId, shareDataObject, function(response) { saveHighlight = response; }); }); userdataObj.on("mydata:postComment", function(commentObj) { for (var i = 0; i < globaledata.length; i++) { if (globaledata[i].id == commentObj.id) { globaledata[i] = commentObj; break; } } }); userdataObj.on("mydata:acceptClick", function(Noteacceptobj) { for (var i = 0; i < noteHighlightData.length; i++) { if (noteHighlightData[i].id == Noteacceptobj.id) { noteHighlightData[i].actionTaken = 'Y'; } } for (var i = 0; i < globaledata.length; i++) { if (globaledata[i].id == Noteacceptobj.id) { globaledata[i].actionTaken = 'Y'; } } var acceptUgcList = { "acceptUgcList": [{ "ugcID": Noteacceptobj.id, "status": 1 }] } syncManager.syncAdapter.acceptCollabData(usertoken, bookId, acceptUgcList, function(response) { if (response.responseCode == 200) { console.log(response, 'acceptCollabData'); } }); if ((unacceptCount - 1) > 0) { $('.shared-note-count')[0].innerHTML = unacceptCount - 1; unacceptCount = unacceptCount - 1; } else { $('.shared-note-count').css("display", "none"); } }); userdataObj.on("mydata:rejectClick", function(Noteacceptobj) { for (var i = 0; i < noteHighlightData.length; i++) { if (noteHighlightData[i].id == Noteacceptobj.id) { noteHighlightData.splice(i, 1); console.log(noteHighlightData[i]); } } for (var i = 0; i < globaledata.length; i++) { if (globaledata[i].id == Noteacceptobj.id) { globaledata.splice(i, 1); } } var acceptUgcList = { "acceptUgcList": [{ "ugcID": Noteacceptobj.id, "status": 0 }] } syncManager.syncAdapter.acceptCollabData(usertoken, bookId, acceptUgcList, function(response) { if (response.responseCode == 200) { console.log(response); } }); if ((unacceptCount - 1) > 0) { $('.shared-note-count')[0].innerHTML = unacceptCount - 1; unacceptCount = unacceptCount - 1; } else { $('.shared-note-count').css("display", "none"); } }); userdataObj.on("mydata:SaveNoteshare", function(ugcData) { togglePopUpContainer('mydata-panel'); isDoneClick = true; var ugcBookList = { /*object contains bookId,book version,createdOn,pageNo,ugcData etc...*/ "ugcBookList": [{ "bookID": bookId.toString(), "bookVersion": "2.0", "ugcList": [ugcData[0]] }] } var object = JSON.parse(decodeURIComponent(ugcBookList.ugcBookList[0].ugcList[0].metadata)); /*ugcData contains bookId,book version,createdOn,pageNo,ugcData etc...*/ if (isServiceAdapator) { syncManager.syncAdapter.saveUGC(usertoken, ugcBookList, function(response) { if (response.responseCode == 200) { console.log(response); var ugcId = response.bookUgcList[0].ugcList[0].id; console.log(ugcId); if (response.responseCode == 200) { ugcData[1].collabData[0].ugcID = response.bookUgcList[0].ugcList[0].id; /*assign value of current note id to noteShareObject*/ /*noteShareData contains list of receivers and ugclist*/ syncManager.syncAdapter.saveCollabData(bookId, usertoken, ugcData[1], function(response) { console.log(response); syncManager.syncAdapter.fetchCollbShareData(usertoken, bookId, function(response) { if (response.responseCode == 200) { console.log(response); } }); }); } else { console.log('Data saving Failed.!') } } }); } var drawcss = { backgroundColor: object.color, //ugcData.ugcBookList[0].ugcList[0].important == "Y" ? "red" : "yellow", color: "", element: "span" } }); // MYData view implementation end
Customization¶
Kitaboo SDK supports a MyData component to show the list of Notes and Highlights available for the book. You can either customize the entire MyData component or make simple changes to the MyData that comes with Kitaboo reader with just changing the font and CSS. If you want to replace the entire MyData with your own, then you can just use the data and create your own view.
1. Basic customization
Using CSS you can customize the following :
1.1. Theme
You can set the theme color using id #mydatalist and its child components
1.2. Changing labels
This will allow you to change label in MyData Panel
userdataObj = new MYData({ container: myDataContainer, locale: { label: { notes: 'Notes', highlight: 'Highlights', myNotes: 'My Notes', myHighlights: 'My Highlights', chapter: 'Chapter:', page: 'Page' }, buttons: { shared: 'Shared with Me', comment: 'Comments', share: 'Share' }, messages: { shareMsg: ' has started sharing data with you.', nodata: 'No data found.' } } });
Example Project¶
The My-data Example project is a sample code reference of SDK Integration with fully functioning My-data Component. Click here to Download the project.
Pen¶
Introduction¶
KitabooSdk supports a feature called "pen marker" which can be utilized to draw/pen-mark, It supports multiple types of lines/shapes of different colors on book pages with various thickness.
Implementation¶
Use the following code to add Pen to your reader :
Note
To display pen cursor dynamically, we use the cursor_png and assign it to cursor, but it needs to be written differently for IE and edge
// resolved IE issue for dynamic cursor var penCursor = "url('" + <basePath> + "css/images/cursor_pen.png') 5 23, auto"; if (BrowserDetect.browser === 'Internet Explorer' || window.navigator.userAgent.indexOf("Edge") > -1) { penCursor = "url('" + <basePath> + "css/images/cursor_pen.cur'), auto"; } /* drawing canvas implementation*/ var drawingOptions = { mode: 'pen', // set mode lineWidth: '3', // starting line width fillStyle: '#FFFFFF', // starting fill style strokeStyle: $('.pick-colors.color-active').css("color"), // start stroke style cursors: penCursor // set to default }; // drawing object for single page drawCanvas = new DrawingCanvas(drawingOptions); /** * if mouse down on single page * @return {object} event * @return {object} event.canvas: current mouse up canvas * @return {object} event.data: current mouse up position * @return {object} event.target: parent or this **/ drawCanvas.on('mouse:down', function(event){ console.log(event, 'drawCanvas mouse:down'); //drawCanvas.tools: tools used for drawing pen and eraser // drawCanvas.defaults.mode: drawing options when creating drawingCanvas Object drawCanvas.tools[drawCanvas.defaults.mode](event.target, event.data); }); /** * if mouse move on single page * @return {object} event * @return {object} event.canvas: current mouse up canvas * @return {object} event.data: current mouse up position * @return {object} event.target: parent or this **/ drawCanvas.on('mouse:move', function(event){ //console.log(event, 'drawCanvas mouse:move'); drawCanvas.tools[drawCanvas.defaults.mode](event.target, event.data); }); /** * if mouse up on single page * @return {object} event * @return {object} event.canvas: current mouse up canvas * @return {object} event.data: current mouse up position * @return {object} event.target: parent or this **/ drawCanvas.on('mouse:up', function(event){ console.log(event, 'drawCanvas mouse:up'); var currentObj = drawCanvas.tools[drawCanvas.defaults.mode](event.target, event.data);; ugcBookList = { "ugcBookList": [{ "bookID": bookId, "bookVersion": "2.0", "ugcList": [currentObj] }] } if (isServiceAdapator && Object.keys(currentObj).length) { /*student can not delete submitted pen data and teacher's annotation*/ var isStudentDataSubmitted = (currentObj.hasOwnProperty('submitted') && currentObj.submitted); if (!isStudentDataSubmitted) { syncManager.syncAdapter.saveUGC(usertoken, ugcBookList, function(response) { if (response.responseCode == 200) { if (drawCanvas.defaults.mode === 'eraser') { for (var i = globaledata.length - 1; i >= 0; i--) { if (currentObj.pageId === globaledata[i].pageId && currentObj.id === globaledata[i].id && currentObj.localId === globaledata[i].localId) { console.log(globaledata[i], 'delete pen data'); globaledata.splice(i, 1); break; } } drawCanvas.deleteDrawingData(currentObj); // delete it from main collection on deleted from server } else { currentObj.id = response.bookUgcList[0].ugcList[0].id; /*update new Id with existing Id*/ drawCanvas.addDrawingData(currentObj); // update id of server if new created } } }); } } else if(Object.keys(currentObj).length){ /** * Test pen without service calls */ if (drawCanvas.defaults.mode === 'eraser') { for (var i = globaledata.length - 1; i >= 0; i--) { if (currentObj.pageId === globaledata[i].pageId && currentObj.id === globaledata[i].id && currentObj.localId === globaledata[i].localId) { globaledata.splice(i, 1); break; } } drawCanvas.deleteDrawingData(currentObj); // delete it from main collection on deleted from server } else { drawCanvas.addDrawingData(currentObj); // update id of server if new created } } console.log(currentObj, 'currentDrawingObj'); }); /* when in 2 page mode always assign left if availabel*/ drawLeftCanvas = new DrawingCanvas(drawingOptions); /** * if mouse down on left page * @return {object} event * @return {object} event.canvas: current mouse up canvas * @return {object} event.data: current mouse up position * @return {object} event.target: parent or this **/ drawLeftCanvas.on('mouse:down', function(event){ console.log(event, 'drawLeftCanvas mouse:down'); drawLeftCanvas.tools[drawLeftCanvas.defaults.mode](event.target, event.data); }); /** * if mouse move on left page * @return {object} event * @return {object} event.canvas: current mouse up canvas * @return {object} event.data: current mouse up position * @return {object} event.target: parent or this **/ drawLeftCanvas.on('mouse:move', function(event){ //console.log(event, 'drawLeftCanvas mouse:move'); drawLeftCanvas.tools[drawLeftCanvas.defaults.mode](event.target, event.data); }); /** * if mouse up on left page * @return {object} event * @return {object} event.canvas: current mouse up canvas * @return {object} event.data: current mouse up position * @return {object} event.target: parent or this **/ drawLeftCanvas.on('mouse:up', function(event){ console.log(event, 'drawLeftCanvas mouse:up'); var currentLeftObj = drawLeftCanvas.tools[drawLeftCanvas.defaults.mode](event.target, event.data);; ugcBookList = { "ugcBookList": [{ "bookID": bookId, "bookVersion": "2.0", "ugcList": [currentLeftObj] }] } if (isServiceAdapator && Object.keys(currentLeftObj).length) { syncManager.syncAdapter.saveUGC(usertoken, ugcBookList, function(response) { if (response.responseCode == 200) { isPenSubmitted = true; if (drawLeftCanvas.defaults.mode === 'eraser') { for (var i = globaledata.length - 1; i >= 0; i--) { if (currentLeftObj.pageId === globaledata[i].pageId && globaledata[i].id === currentLeftObj.id && globaledata[i].localId === currentLeftObj.localId) { console.log(globaledata[i], 'eraser'); globaledata.splice(i, 1); break; } } drawLeftCanvas.deleteDrawingData(currentLeftObj); // delete it from main collection on deleted from server } else { currentLeftObj.id = response.bookUgcList[0].ugcList[0].id; /*update new Id with existing Id*/ drawLeftCanvas.addDrawingData(currentLeftObj); // update id of server if new created } } }); } else if(Object.keys(currentLeftObj).length){ /** * Test pen without service calls */ if (drawLeftCanvas.defaults.mode === 'eraser') { for (var i = globaledata.length - 1; i >= 0; i--) { if (currentLeftObj.pageId === globaledata[i].pageId && globaledata[i].id === currentLeftObj.id && globaledata[i].localId === currentLeftObj.localId) { console.log(globaledata[i], 'eraser'); globaledata.splice(i, 1); break; } } drawLeftCanvas.deleteDrawingData(currentLeftObj); // delete it from main collection on deleted from server } else { drawLeftCanvas.addDrawingData(currentLeftObj); // update id of server if new created } } console.log(currentLeftObj, 'currentDrawingObj'); });;
Customization¶
For pen tool, we have to manage pop-ups for pen colors, thickness etc., using defined user controls.
Create view to display pen colors using repeat and on colors click call these two methods
1) setCurrentTool('pen');
2) onColorClick(value) // color value
/* Function to set tool Pen or Eraser */ function setCurrentTool(type) { var options = {}; if (type === 'eraser') { // resolved IE issue for dynamic cursor var eraserCursor = "url('" + basePath + "css/images/eraser.png') 6 24, auto"; if (BrowserDetect.browser === 'Internet Explorer' || window.navigator.userAgent.indexOf("Edge") > -1) { eraserCursor = "url('" + basePath + "css/images/eraser.cur'), auto"; } options = { cursors: eraserCursor } // x, y coo-dinates are also used for delete logic } else { // resolved IE issue for dynamic cursor var penCursor = "url('" + basePath + "css/images/cursor_pen.png') 5 23, auto"; if (BrowserDetect.browser === 'Internet Explorer' || window.navigator.userAgent.indexOf("Edge") > -1) { penCursor = "url('" + basePath + "css/images/cursor_pen.cur'), auto"; } options = { cursors: penCursor } } if (drawCanvas) { drawCanvas.setCurrentTool(type); drawCanvas.setDrawOption(options); } if (drawLeftCanvas) { drawLeftCanvas.setCurrentTool(type); drawLeftCanvas.setDrawOption(options); } } function onColorClick(colorElem) { $('.pick-colors').removeClass('color-active'); $(colorElem).addClass('color-active'); console.log($(colorElem).css("color"), 'onColorClick'); drawCanvas.setColor($(colorElem).css("color")); if (drawLeftCanvas) { drawLeftCanvas.setColor($(colorElem).css("color")); } } // then add all the canvas code mentioned above for enabling Canvas
We need to add all the codes for canvas mentioned above to enable drawing on page and then it will work.
Thumbnail View¶
Introduction¶
Kitaboo Sdk exposes a component which helps the user to see a small image representation of pages in the currently opened Book. Here user can navigate to the specific page by clicking on them.
Implementation¶
/** * Custom tocxml.xml created by hurix holds thumbnail data * manifest tags inside opf contains information */ if (book.bookdata.manifest.hasOwnProperty('tocxml')) { Thumbnail implementation can be achieved by using following steps: // check div show and hide functionality inside togglePopUpContainer function // container to hold toc view var container = document.getElementById('thumbnailholder'); var resourceContainer = document.getElementById('resourcechild'); /** * @param {dom} contianer: to hold the thumbanil view dom * manifest tags inside opf contains information of path */ var thumbnailParams = { container: container }; book.thumbnailViewManager = new ThumbnailView(thumbnailParams); book.thumbnailViewManager.createThumbnailView(book.chapters); /* * jump to page. take out page from display number */ book.thumbnailViewManager.on('thumbnail:itemclick', function(event) { var pageNum = book.displayNum_pageNum_map[event.data.displayNum]; render.navigateToPage(parseInt(pageNum)); toggleThumbnailView(); }); // page history previous book.thumbnailViewManager.on('page:history_prev', function(event) { currentPrevPage = book.displayNum_pageNum_map[event.data]; render.navigateToPage(currentPrevPage); }); // page history next book.thumbnailViewManager.on('page:history_next', function(event) { currentNxtPage = book.displayNum_pageNum_map[event.data]; render.navigateToPage(currentNxtPage); }); // navigate to page book.thumbnailViewManager.on('page:gotoPage_value', function(event) { var pageNum = document.getElementById('input_value').value; pageNum = book.displayNum_pageNum_map[pageNum]; render.navigateToPage(parseInt(pageNum)); });
Customization¶
For thumbnail we can customize the look and theme using css
Markup¶
Introduction¶
KitabooSdk facilitates a user to add different icons as a "Markup", which makes the user experience more interactive on pages.
KitabooSdk supports the following types of Markup :
GLOSSARY, INTERNAL, WEB_ADDRESSES, RESOURCE, IMAGE, VIDEO, ACTIVITY, ANIMATIONS, DOCUMENTS, HTML_WRAP, KITABOO_WIDGET, PDF, MULTIPLE_LINK, AUDIO, AUDIO_SP, COMMENTS, INPUT, BUTTON, RADIOBUTTON, CHECKBOX, LINK, QA ACTIVITY, AUDIO_SYNC, ACTIVITY_INJECTION, INTERACTIVE, SLIDESHOW, YOUTUBE STREAMING, KALTURA STREAMING, EXTERNAL_IMAGE, EXTERNAL_AUDIO, EXTERNAL_VIDEO, EXTERNAL_WEB_LINK, EXTERNAL_DOCUMENTS, EXTERNAL_HTML_WRAP, STANDALONE_INSTRUCTION, VIMEO_VIDEO
Implementation¶
Use the following code to add Markup to your reader :
/** * event for markup's click on page * @return {object} markup * @return {object} markup.id: markup id which is clicked * @return {object} markup.type: type of clicked markup on page.ie., image, video, audio etc * @return {object} markup.pageId: id of the page on which resource was clicked * @return {object} markup.title: title given to markup if any * @return {object} markup.alt: alt given to markup if any * @return {object} markup.basePath: path till parent folder * @return {object} markup.extra: extra information related to the markup **/ render.on('markup:clicked', function(markup) { console.log(markup, 'markup:clicked'); openMarkup(markup); }); /* * check the markup and open accordingly */ function openMarkup(markup) { closeAllPopup(); var type = markup.type; switch (type) { case 'documents': var blob = markup.markupUrl if (blob.indexOf('.pdf') > 0) { var appRootURL = window.location.href.substring(0, window.location.href.indexOf('#')); appRootURL = appRootURL || window.location.href; appRootURL = appRootURL.substring(0, appRootURL.lastIndexOf('/') + 1); if ((BrowserDetect.browser === 'Internet Explorer') || (window.navigator.appName == "Netscape"&& window.navigator.appVersion.indexOf('Edge') > -1)) { var docViewer = window.open(appRootURL + 'views/docViewer.html'); if (docViewer.attachEvent) { docViewer.attachEvent('onload', pdfOnLoad(docViewer, blob)); } else if (docViewer.addEventListener) { docViewer.addEventListener('load', pdfOnLoad(docViewer, blob), false); } else { docViewer.document.addEventListener('load', pdfOnLoad(docViewer, blob), false); } } else { var docViewer = window.open(appRootURL+ 'views/docViewer.html'); docViewer.onload = function() { if (docViewer.document.getElementsByTagName('iframe') !== undefined) { docViewer.document.getElementsByTagName('iframe')[0].src = blob } else { var ifrm = document.createElement("iframe"); ifrm.setAttribute("src", blob); docViewer.document.body.append(ifrm); } }; } } else { window.open(blob); } break; case 'audio': $('.markup .container').draggable({ iframeFix: true, handle:'.drag-handler-icon', containment: ".epub-viewer" }); $('.markup .container').find('audio')[0].src = markup.markupUrl; $('.markup .container').find('audio')[0].autoplay = true; $('.markup').show(); break; case 'htmlwrap': /* initiliazed prettyPhoto for */ $().prettyPhoto({ social_tools: false, deeplinking: false, opacity: 0.2, type: markup.type, caption: markup.title}); /* type htmlwrap */ $.prettyPhoto.open(markup.basePath+ markup.markupUrl, '', markup.title); break; case 'kaltura_video': //Use Auth and signed the URL // markup object contains all the information below are the properties /** * {object} markup * {object} markup.id: markup id which is clicked * {object} markup.type: type of clicked markup on page.ie., image, video, audio etc * {object} markup.pageId: id of the page on which resource was clicked * {object} markup.title: title given to markup if any * {object} markup.alt: alt given to markup if any * {object} markup.markupUrl: Url for the mark * {object} markup.basePath: path till parent folder * {object} markup.extra: extra information related to the markup **/ // Once you get signed url for Kaltura after Auth request, open it using following code /* type kaltura_video $().prettyPhoto({social_tools: false, deeplinking: false, opacity: 0.2, allow_resize: true, type: markup.type}) $.prettyPhoto.open(singed_url, '', markup.title);*/ break; case 'audioSync': // audio implementation is integrated inside shell/js/custom_audio_player.js render.loadAndParseCuePoints(markup.cuePointsXMLPath, function(data) { custom_audio.addSource(markup.markupUrl); $('.markup .container').draggable({ iframeFix: true, handle: '.drag-handler-icon', containment: ".epub-viewer" }); $('.markup').show(); var target = render.getAudioSyncSpan(markup); // get the span which will highlight the word custom_audio.bind('play', function() { trackCurrentTime.call(this.sound); // playing audio object }); /* highlight the sync word on time update*/ function trackCurrentTime() { var currentTime = this.currentTime; for (var i = 0; i < data.length; i++) { if ((currentTime >= data[i].start && currentTime <= data[i].end)) { $(target).show().css({ width: data[i].width, height: data[i].height, left: data[i].x, top: data[i].y }); } } requestAnimFrame(trackCurrentTime.bind(this)); // rather then using interval use window.requestAnimationFrame } }); break; default: /* type image, video */ $().prettyPhoto({social_tools: false, deeplinking: false, opacity: 0.2, allow_resize: true, type: markup.type}) $.prettyPhoto.open(markup.markupUrl, '', markup.title); break; } } /** * PDF loaded event */ function pdfOnLoad(docViewer,blob){ window.setTimeout(function() { docViewer.pdfLoad(blob); }, 500); } /** * close the audio markup */ function closeMarkup(){ $('.markup').find('audio')[0].pause(); $('.markup').find('audio')[0].currentTime = 0; $('.markup').hide(); } function closeAllPopup(){ $('.thumb-nail').removeClass('active'); $('.thumbnail-holder').hide(); closeDrawingContainer(); togglePopUpContainer(); closeMarkup(); }
Customization¶
- We can customize markup by using different Icons in resource tab as well as page.
- We can also provide custom popup for all markup and open it differently in cases below :
Example
We have created a different popup for customizing the view of video popup and we are using a different library to play the video. So, you can see the sample code below to launch the video in different popup in case of video.
function openMarkup(markup) { closeAllPopup(); var type = markup.type; switch (type) { case 'video': openMP4VideoMarkup(markup); break; } function openMP4VideoMarkup(markup) { var fileType = markup.markupUrl.substring(markup.markupUrl.lastIndexOf('.') + 1, markup.markupUrl.length); // return file type ex: mp4, webm, ogg var videoTitle = markup.title; // video title // object that contains media information var media = { sources: [{ src: markup.markupUrl, type: 'video/' + fileType, }], tracks: markup.subtitle ? [{ kind: 'subtitles', label: 'English subtitles', src: '', srclang: 'en', default: true }] : [], }; var infoObj = { templateUrl:<videoPlayerView> }; openModalPopup('$event', URL, 'parent'); };
Service Adaptor¶
Introduction¶
- To use the Kitaboo services, "Kitaboo SDK" provides an adapter called "syncManager.syncAdapter" which uses Kitaboo services and supports the required API calls [ ie; Fetch/Save UGC request and others].
- Service triggering from Reader : services can be triggered from Reader on specific event.
Example
We are triggering the "FetchUGC" request while opening the book. Similarly, another Service API can be triggered based on the requirement at the Reader end.
Service Adaptor used to call the services to save data to server, login etc.,
Use the following code to add Service Adaptor to your project :
/** * service manager implementation **/ // code to extent ServiceAdapter default function /*var kitabooadapter = function() {}; kitabooadapter.prototype = Object.create(ServiceAdapater); kitabooadapter.prototype.login = function(usertocke) {}*/ var syncManager = new SyncManager(ServiceAdapater); syncManager.syncAdapter.setHost('https://qc.kitaboo.com'); // default setting to qc /** * uncomment below code if already login and have BookID * comment code for login and getUserBookList service */ // syncManager.syncAdapter.setUserToken(sessionStorage.getItem('cloudUserToken')); // syncManager.syncAdapter.setBookID(sessionStorage.getItem("cloudBookId")); //syncManager.syncAdapter.setLastPageFolioIdID(sessionStorage.getItem('lastPageFolio')); /*var userVO = {}; userVO.firstName = sessionStorage.getItem("cloudFirstName"); userVO.lastName = sessionStorage.getItem("cloudLastName"); userVO.userRole = sessionStorage.getItem("cloudRoleName"); userVO.userID = sessionStorage.getItem("cloudUserId"); userVO.userName = sessionStorage.getItem("cloudUserName"); syncManager.syncAdapter.setUserVO(userVO);*/ /** * calling login service and getting userToken * set userToken * @param {string} userid * @param {string} password * @retun {string} userToken **/ syncManager.syncAdapter.login('fib35@yopmail.com', 'kitaboo@123',function(response){ syncManager.syncAdapter.setUserToken(response.userToken); var userVO = {}; userVO.firstName = response.user.firstName; userVO.lastName = response.user.lastName; userVO.userRole = response.user.roles[0].name; userVO.userID = response.user.userID; userVO.userName = response.user.userName; syncManager.syncAdapter.setUserVO(userVO); username = syncManager.syncAdapter.userVO.userName; userRole = syncManager.syncAdapter.userVO.userRole; usertoken = syncManager.syncAdapter.userToken; /** * fetch user booklist from server * @param {string} userToken * @return {[]} return booklist */ syncManager.syncAdapter.getUserBookList(usertoken, function(response){ syncManager.syncAdapter.setBookID(response.bookList[0].book.id); syncManager.syncAdapter.setLastPageFolioIdID(response.bookList[0].book.classList[0].lastPageFolio); bookId = syncManager.syncAdapter.bookid; lastPageFolioId = syncManager.syncAdapter.lastPageFolioId; /* * get either shared or received data for validate user * @param {string} bookId * @param {string} usertoken * @param {number} timestamp */ syncManager.syncAdapter.fetchBookClassInfo(bookId, usertoken, function(response){ settingData = response; }); /** * fetch UGC data from server * @param {string} bookId * @param {string} usertoken * @param {number} timestamp */ syncManager.syncAdapter.fetchUGC(bookId, usertoken, Math.round(new Date().getTime()/1000), function(response){ if(response.responseCode == 200){ var ugcList = response.bookUgcList[0].ugcList; for (var i = 0; i < ugcList.length; i++) { var currentUGCVO = ugcList[i]; if ((currentUGCVO.type === 1 || currentUGCVO.type === 2) && currentUGCVO.status != 'DELETE') { var isUgcData = currentUGCVO.hasOwnProperty('ugcData') var ugcData = currentUGCVO.ugcData; var metadata = JSON.parse(decodeURIComponent(currentUGCVO.metadata)); var isImp = (currentUGCVO.important === 'Y') ? true : false; // color property not found in metadata on server if(!metadata.hasOwnProperty('color')){ if(isImp){ metadata.color = '#FF0000'; }else{ metadata.color = '#FFFF00'; } currentUGCVO.metadata = ObjectToEcodeURI(metadata); } }else if(currentUGCVO.type === 4 ){ bookmarkobj.bookmarkManager.listofbookmarks.push(currentUGCVO); } renderUGCDataOnPage(currentUGCVO); globaledata.push(currentUGCVO);// set user UGC data. Notes, Highlight etc., } } }); }); });
Fit Height, Fit Width & Zoom¶
Introduction¶
Pages by default fit-to-height. A user can zoom the page as well as make a page to its width.
Implementation¶
Add the following code to your reader :
/** * fit the page to width or height **/ function fitWidthHeight(elem) { highlightEnable = false; closeAllPopup(); lastopen = ''; $(elem).toggleClass('fith-icon'); render.fitPage(); // method to fit the page } /** * call this on zoom buttom * zoomin zoomout the page **/ function zoomInOut(elem) { highlightEnable = false; closeAllPopup(); lastopen = ''; $(elem).toggleClass('zoom-out-icon'); $('.zoom-slider-container').animate({ width: 'toggle' }, 500); } /** * function called when slider change triggers * zoom slider */ $(".zoomSlider").slider({ min: min_scale, max: max_scale, animate: true, step: 0.1, slide: function(event, ui) { render.zoomBy(ui.value); // send the zoom value to scale the page ie., 0.3 console.log(ui.value, 'zoomSlider'); } });
Single Page and Double Page View¶
Introduction¶
KitabooSdk facilitates Single Page and Double Page view as well to enhance Readability and User Experience
Implementation¶
Use the following code for your reader :
setPageMode needs boolean value to switch the view in single or double page so it you pass true it will render double page and vice versa render.setPageMode(isDouble)
Dictionary¶
Introduction¶
Dictionary implementation can be achieved by following the below mentioned steps :
- Add the dictionary icon in highlight pop-view at the reader's end
- Get Highlighted text-related data from Dictionary
- Handling click event of Dictionary icon
Implementation¶
Adding dictionary icon in highlight pop view :
/** * Highlight and Note contextual menu configuration object * @param {object} config * @param {string} [config.textSelectionCSS] : */ var config = { textSelectionCSS: "color:white; background:red", defaultHighlighCSS: "border-radius: 23px;opacity: 1.0;padding-left: 5px;padding-right: 5px;background-color: rgba(0, 0, 0, 0.6) !important;display:none;height:50px;", stickynotetext: 'S', contextualnoteicon: 'V' } // create highlight class object var highlight = new KitabooHighlight(config); /** * Define the item that will shown in context menu for document selection * eg., highlight, notes * refer item1 below * @properties {object.icon}: icon or placeholder for item * @properties {object.id}: unique id which represents item * @properties {object.css}: background-color, position of item in content menu */ var item1 = { icon: "e", id: 100, css: "background: transparent;border: 0px;float: left;width: 50px;color: yellow; font-size: 1.5em; font-family: kitabooread;" } // add the create object in highlight object. when user selects text on document. // Popup will contain the above custom object(item1, item2) highlight.addItem(item1);
Get the Highlighted text related data from Dictionary :
// once DOM selection complete. show popup for editing render.on("highlight:section", function(textobject, page) { highlight.show(textobject, page); });
Handling click event of Dictionary icon :
/* * Event dispatched on custom item clicked in context menu * Custom item create by user and information * Using which he/she can manipulate the selection on DOM */ highlight.on("highlight:onitclemClick", function(highlightobject) { if (highlightobject.item.id == '100') { // highlightobject.item.id: unique id given by user when created highlight // dictionary implementation will go here } });